首页 > 其他分享 >BBS项目练习

BBS项目练习

时间:2023-01-02 21:33:16浏览次数:42  
标签:verbose 项目 models 练习 length CharField BBS class name

BBS项目练习

此项目是对博客园软件的简单模仿,旨在整合django的知识点。

七张信息表

  1. 用户表(与站点一对一)
  2. 站点表
  3. 文章表(与站点一对多)
  4. 文章分类表
  5. 文章标签表
  6. 点赞点踩表
  7. 评论表

建立以上七张表的模型表:

from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.

class UserInfo(AbstractUser):
    """用户信息表:继承了auth类"""
    tel = models.CharField(verbose_name='电话号码', max_length=5)  # 5位号码模拟
    avatar = models.FileField(verbose_name='用户头像', upload_to='avatar/', default='avatar/默认头像.png', )
    register_time = models.DateField(verbose_name='注册时间', auto_now_add=True)

    site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)


class Site(models.Model):
    """个人站点表"""
    name = models.CharField(verbose_name='站点名称', max_length=16)
    title = models.CharField(verbose_name='站点标题', max_length=16)
    theme = models.TextField(verbose_name='站点样式')  # 这里简单模拟一下存储样式


class Article(models.Model):
    """文章表"""
    title = models.CharField(verbose_name='文章标题', max_length=32)
    brief = models.CharField(verbose_name='文章简介', max_length=100)
    content = models.TextField(verbose_name='文章内容')
    load_time = models.DateTimeField(verbose_name='发布时间', auto_now_add=True)
    # 文章字段扩展(需要代码层面的自动更新)
    comments_num = models.IntegerField(verbose_name='评论数', default=0)
    like_num = models.IntegerField(verbose_name='点赞数', default=0)
    unlike_num = models.IntegerField(verbose_name='点踩数', default=0)
    read_num = models.IntegerField(verbose_name='阅读数', default=0)

    # 文章外键字段
    site = models.ForeignKey(to='Site', on_delete=models.CASCADE)
    article_class = models.ForeignKey(to='ArticleClass', on_delete=models.CASCADE)
    tag = models.ManyToManyField(to='ArticleTag')


class ArticleClass(models.Model):
    """文章分类表"""
    # 文章分类一对多文章
    name = models.CharField(verbose_name='分类名称', max_length=10)
	# 也是从属于站点的
    site = models.ForeignKey(to='Site', on_delete=models.CASCADE)


class ArticleTag(models.Model):
    """文章标签表"""
    # 文章标签多对多文章
    tag = models.CharField(verbose_name='文章标签', max_length=8)
	# 也是从属于站点的
    site = models.ForeignKey(to='Site', on_delete=models.CASCADE)


class PointLike(models.Model):
    """点赞点踩表"""
    # 外键字段
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
    # 某用户对某文章的推荐态度
    up_or_down = models.BooleanField(verbose_name='点赞或点踩', null=True)


class Comment(models.Model):
    """评论表"""
    # 外键字段
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
    # 某用户对某文章的评论信息
    context = models.CharField(verbose_name='评论内容', max_length=100)
    comment_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)
    parent = models.ForeignKey(to='self', verbose_name='根评论', on_delete=models.CASCADE)  # 自关联

注册功能

此次尝试通过ajax请求来完成提交表单,注意视图层和模板层的变化

视图层

视图层在get请求过来时会返回一个纯净的表单界面,而在post请求过来时会进行一系列的校验,并返回一个可能有含错误信息的表单界面。

def register(request):
    register_obj = myforms.RegisterForm()  # 将表单类直接单独存放到另外的py文件
    if request.method == 'POST':
        # 用信息的表单类
        register_obj = myforms.RegisterForm(request.POST)
        # ajax请求通常以json格式的自定义对象(字典)通信
        back_dict = {}
        if register_obj.is_valid():
            # 如果表单数据符合要求,处理数据,并完成注册
            back_dict['code'] = 10000  # 自定义状态码
            cleaned_data = register_obj.cleaned_data
            cleaned_data.pop('confirm_password')
            # 如果没有那就不给这个生成这个键,创建数据时按默认头像。
            if request.FILES.get('avatar'):  
                cleaned_data['avatar'] = request.FILES.get('avatar')
            models.UserInfo.objects.create_user(**cleaned_data)
            back_dict['url'] = reverse('login')
            back_dict['msg'] = '注册成功'
        else:
            # 否则返回错误信息
            back_dict['code'] = 10001
            back_dict['msg'] = register_obj.errors

        return JsonResponse(back_dict)
    return render(request, 'registerPage.html', locals())

模板层

主要实现了以下内容:

  • 渲染标签
  1. 提交表单的ajax请求,并处理后端返回过来的信息
    • 如果是注册成功的状态码,跳转到指定界面
    • 如果是其他状态码,说明错误,将错误信息渲染到界面上
  2. 当用户上传头像图片时,实时将其渲染到界面上(纯前端)
  3. 当用户聚焦到输入框时,将错误信息及样式移除(纯前端)
<div class="container">
    <div class="col-md-6 col-md-offset-3">
        <!--表单标签-->
        <form id="regi_form" action="" method="post">
            <!--csrf校验-->
            {% csrf_token %}
            <!--循环生成form组件的input标签-->
            {% for regi in register_obj %}
                <div class="form-group">
                    <label for="{{ regi.auto_id }}">{{ regi.label }}</label>
                    {{ regi }}
                    <span style="color: red" class="pull-right"></span>
                </div>
            {% endfor %}
			<!--头像提交是单独的-->
            <div class="form-group">
                <label for="avatar">头像
                    <img id="myimg" src="{% static '默认头像.png' %}"
                         style="width:120px; box-shadow: 5px 5px 5px gray; border-radius: 50%"
                         alt="">
                </label>
                <input type="file" id="avatar" name="avatar" value="{% static '默认头像.png' %}" style="display: none">
			<!--提交按钮-->
            </div>
            <div class="form-group">
                <input type="button" id="regi_submit" value="提交" class="btn btn-success form-control">
            </div>
        </form>
    </div>
</div>

<!--js代码-->
<script>
    // 注册按钮发送ajax
    $('#regi_submit').click(function () {
        let newFormObj = new FormData()
        let regiObj = $('#regi_form').serializeArray()
        console.log(regiObj)
        $.each(regiObj, function (index, regiObj) {
            newFormObj.append(regiObj.name, regiObj.value)
        })
        newFormObj.append('avatar', $('#avatar')[0].files[0])
        $.ajax({
            url: '',
            type: 'post',
            data: newFormObj,
            contentType: false,
            processData: false,
            success: function (args) {
                if (args.code === 10000){
                    window.location.href = args.url
                }else{
                    let eleErrors = args.msg
                    $.each(eleErrors,function (key, errorsList) {
                        $('#id_' + key).next().text(errorsList[0]).parent().addClass('has-error')
                    })  // each
                }  //else
            }  // success
        }) // ajax
    })  // click
    // 上传图片文件时实时展示到页面上
    $('#avatar').change(function () {
        let fileReaderObj = new FileReader()
        fileReaderObj.readAsDataURL(this.files[0])
        fileReaderObj.onload = function () {
            $('#myimg').attr('src', fileReaderObj.result)
        }
    })
    // 聚焦时,移除错误信息
    $('input').focus(function () {
        $(this).next().text('').parent().removeClass('has-error')
    })
</script>

表单类

表单类中除了帮助我们快速生成标签,也可以单独的添加widget参数来修改属性,包括class属性,所以可以利用这一点修改样式。

class RegisterForm(forms.Form):
    username = forms.CharField(min_length=3, max_length=8, label='用户名',
                               widget=forms.widgets.TextInput(
                                   attrs={
                                       'class': 'form-control'
                                   }
                               )
                               )
    password = forms.CharField(min_length=3, max_length=8, label='密码',
                               widget=forms.widgets.PasswordInput(
                                   attrs={
                                       'class': 'form-control'
                                   }
                               )
                               )
    confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
                                       widget=forms.widgets.PasswordInput(
                                           attrs={
                                               'class': 'form-control'
                                           }
                                       )
                                       )
    email = forms.EmailField(label='邮箱', widget=forms.widgets.EmailInput(
        attrs={
            'class': 'form-control'
        }
    ))
    tel = forms.CharField(label='电话', required=False,
                          validators=[
                              RegexValidator('^1[0-9]{4}$', '号码必须是1开头的5位数字'),
                          ],
                          widget=forms.widgets.TextInput(
                              attrs={
                                  'class': 'form-control'
                              }
                          )
                          )
	# 钩子函数
    def clean_username(self):
        username = self.cleaned_data.get('username')
        user_obj = models.UserInfo.objects.filter(username=username)
        if user_obj:
            self.add_error('username', '用户名已存在')
        return username

    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password', '两次密码不一致')
        return self.cleaned_data

标签:verbose,项目,models,练习,length,CharField,BBS,class,name
From: https://www.cnblogs.com/Leethon-lizhilog/p/17020574.html

相关文章

  • 2023/01 LeetCode练习
    ......
  • BBS项目
    项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试5.交付上线项目流程仿博客园项目 核心:文章的增删改查表分析 先确定表的数量,在确定表的基础字段,最......
  • BBS(仿博客园项目)-基于django框架详解(包含图文)
    BBS项目(仿博客园项目)项目简介使用python中django框架开发类似博客园基本功能的小项目技术:django框架、编程语言(python3.8)、前端基础(bootstarp3.4.1,jQuery3.5.1)、......
  • bbs项目(部分讲解)
    项目开发基本流程需求分析架构设计分组开发提交测试交付上线项目分析流程仿BBS项目:仿造博客园项目核心:文章的增删改查技术栈Django、MySQL功能注册......
  • Vue-element-template项目学习笔记
    1.vue在css引入背景图片报错:Modulenotfound:Error:Can'tresolve'../../images/icons/loading2.gif'in'/home。报错信息就是找不到路径,我是这样的写法:backgroun......
  • 第20章_ CSS-练习
    ​  层叠样式表(英文全称:CascadingStyleSheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可......
  • 第20章_ CSS-练习
    ​  层叠样式表(英文全称:CascadingStyleSheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可......
  • bbs项目day01---注册登录
    今日内容概要主题:仿BBS项目项目开发基本流程项目分析(表)项目注册功能项目登录功能今日内容详细项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测......
  • 04使用Pinia实现Vuex项目全球化
    在上一章中使用的Vuex作为状态管理实现的全球化,这篇文章使用Pinia作为状态管理。现有用户可能对Vuex更熟悉,它是Vue之前的官方状态管理库。由于Pinia在生态系统中能......
  • BBS项目
    目录表之间关系表之间关系先确定表的数量再确定表的基础字段最后确定表的外键字段用户表替换auth_user表并扩展额外的字段(电话号码、头像、注册时间)classUserInfo......