zoukankan      html  css  js  c++  java
  • Django—BBS注册页面

     一、数据库表分析

     1、首先是用户表,用户表继承Django自带的auth_user表,目的是可以使用Django封装好的方法,不用自己手动写cookie和session操作,还可以自定义字段

    2、个人站点表,和用户是一对一关系,一个用户都有一个站点

    3.文章表,字段有标题和内容,并且还应该有文章的分类和标签,文章只能有一个分类,比如说这篇文章是Python,那篇是前端,但是一个文章可以有多个标签,所以应该还有文章分类表(和文章表是一对多的关系),文章标签表(和文章表是一对多的关系)

    4.文章分类表

    5.文章标签表

    6.评论表,和用户是一对一的关系

    7.论坛怎么能没有点赞评论,所以加一个点赞点踩表,一个用户一篇文章只能点一次赞或点一次踩,所以是一对多关系

     关系图

    二、表的建立

    使用的是mysql

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    #导入AbstractUser类,继承之后,Django自带的Auth_user就被替换了
    # Create your models here.
    
    
    class UserInfo(AbstractUser):
        # 自定义字段
        phone = models.CharField(max_length=32)
        avatar = models.FileField(upload_to='avatar/',default='avatar/default.png')
        # 用户上传头像,upload_to是头像保存的位置,default是用户默认的头像
        create_time = models.DateField(auto_now_add=True)
        # 关联个人页表
        blog = models.OneToOneField(to='Blog',null=True)
    
    class Blog(models.Model):
        site_name = models.CharField(max_length=32)
        site_title = models.CharField(max_length=64)
        # 个人站点的样式文件 存该样式文件的路径
        theme = models.CharField(max_length=64)
    
    #种类表
    class Category(models.Model):
        name = models.CharField(max_length=32)
        blog = models.ForeignKey(to='Blog', null=True)
    
    #标签表
    class Tag(models.Model):
        name = models.CharField(max_length=32)
        blog = models.ForeignKey(to='Blog', null=True)
    
    #文章表
    class Article(models.Model):
        title = models.CharField(max_length=32)
        desc = models.CharField(max_length=255)
        # 存大段文本
        content = models.TextField()
        create_time = models.DateField(auto_now_add=True)
        # 文章的评论数,点赞数,点踩数,虽然有评论表,点赞表,点踩表,但是每次获取数据都是一次查询,速度会很慢,所以直接在文章表里添加
        comment_num = models.IntegerField(default=0)
        up_num = models.IntegerField(default=0)
        down_num = models.IntegerField(default=0)
        blog = models.ForeignKey(to='Blog', null=True)
        category = models.ForeignKey(to='Category',null=True)
        tags = models.ManyToManyField(to='Tag',through='Article2Tag',through_fields=('article','tag'))
    
    
    class Article2Tag(models.Model):
        article = models.ForeignKey(to='Article')
        tag = models.ForeignKey(to='Tag')
    
    class UpAndDown(models.Model):
        user = models.ForeignKey(to='UserInfo')
        article = models.ForeignKey(to='Article')
        is_up = models.BooleanField()
    
    
    class Comment(models.Model):
        user = models.ForeignKey(to='UserInfo')
        article = models.ForeignKey(to='Article')
        content = models.CharField(max_length=255)
        # 自己是自己的外键,回复如果有其他回复,那么他的parent就是第一个楼层,否则默认是null
        parent = models.ForeignKey(to='self',null=True)
    models.py

    还要在setting文件里:添加你继承AbstractUser的表名

    AUTH_USER_MODEL='app01.UserInfo'

    执行数据库迁移命令

    python manage.py makemigrations
    python mange.py migrate

    三、注册页面

    完成效果:

    forms类的创建

    from django import forms
    from . import models
    
    class MyForm(forms.Form):
        username = forms.CharField(label='用户名',max_length=14,min_length=3,error_messages={
            'max_length':'用户名不能超过14位!',
            'min_length':'用户名不能少于3位!',
            'required':'用户名不能为空!'
        },widget=forms.TextInput(attrs={'class':'form-control'}))
        password = forms.CharField(label='密码', max_length=14, min_length=3, error_messages={
            'max_length': '密码不能超过14位!',
            'min_length': '密码不能少于3位!',
            'required': '密码不能为空!'
        }, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
        confirm_password = forms.CharField(label='确认密码', max_length=14, min_length=3, error_messages={
            'max_length': '确认密码不能超过14位!',
            'min_length': '确认密码不能少于3位!',
            'required': '确认密码不能为空!'
        }, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
        email = forms.EmailField(label='邮箱',error_messages={
            'required':'邮箱不能为空!',
            'invalid':'邮箱格式错误!'
        },widget=forms.EmailInput(attrs={'class':'form-control'}))
    
        #局部钩子
        def clean_username(self):
            #获取用户传来的已通过form组件验证的username
            username = self.cleaned_data.get('username')
            #在数据库的UserInfo表内的username做匹配,取到对象
            user_obj = models.UserInfo.objects.filter(username=username).first()
            #判断对象存不存在,不存在则创建,存在则返回
            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
    myforms.py

    前端页面的搭建

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
        <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
        <style>
            body {
                background-color: #eeeeee;
            }
        </style>
    
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-4 col-md-offset-4">
                <h2 class="text-center">注册</h2>
                <hr>
                <form id="myform">
                {% csrf_token %}
                    {% for form in form_obj %}
                        <div class="form-group">
                            <label for="{{ form.auto_id }}">{{ form.label }}</label>
                            {{ form }}
                            <span class="errors pull-right" style="color: red"></span>
                        </div>
                    {% endfor %}
                </form>
                <div class="form-group">
                    <label for="id_myfile">头像
                        <img src="/static/image/default.jpg" alt="" width="60" style="margin-left: 20px" id="id_img">
                    </label>
                    <input type="file" name="myfile" id="id_myfile" style="display: none">
                </div>
                <button class="pull-right btn btn-primary  btn-block" id="id_submit">注册</button>
            </div>
        </div>
    </div>
    
    //背景动态效果 可以直接复制使用 <script type="text/javascript" color="87,0,86" opacity='1' zIndex="-2" count="99" src="//cdn.bootcss.com/canvas-nest.js/1.0.1/canvas-nest.min.js"></script>

    后端代码

    def register(request):
       #自定义状态码,等会ajax要用到
        respone_code={'code':100,'msg':''}
       #初始化forms组件
        form_obj=myforms.RegForm()
    
       #渲染注册页面,locals()把from_obj,response_code传到了前端,起码目前是这样
        return render(request,'register.html',locals())

    这只是get请求的代码

     上传头像

     //上传头像并替换
        $('#id_myfile').change(function () {
            // 先获取用户上传的文件对象
            let fileObj = this.files[0];
            // 生成一个内置对象
            let fileReader = new FileReader();
            // 将文件对象传递给内置对象
            fileReader.readAsDataURL(fileObj);
            // 将读取出文件对象替换到img标签
            fileReader.onload = function () {  // 等待文件阅读器读取完毕再渲染图片
                $('#id_img').attr('src', fileReader.result)
            }
        });

    ajax异步提交

     $('#id_submit').click(function () {
            //生成一个Formdata对象
            let formData = new FormData();
            //$('#myform').serializeArray()是form表单中的所有数据,自动获取form表单中所有input框键值对,用each循环取出来
            $.each($('#myform').serializeArray(), function (index, obj) {
                //只是添加了普通的键值对,文件对象需要你手动添加
                formData.append(obj.name, obj.value)
            });
            {#console.log($('#myform').serializeArray())#}
            //手动添加文件对象
            formData.append('myfile', $('#id_myfile')[0].files[0]);
            $.ajax({
                url: '',
                type: 'post',
                data: formData,
                processData: false, // 告诉浏览器不要处理我的数据
                contentType: false, // 不要用任何的编码,就用我formdata自带的编码格式,django能够自动识别改formdata对象
                success: function (data) {
                    if (data.code == 100) {
                        /*跳转到登录界面
                        location.href  获取URL
                        location.href="URL" // 跳转到指定页面
                        location.reload() 重新加载页面*/
                        location.href = data.url
                    } else {
                        $.each(data.msg, function (index, obj) {
                            let targetId = '#id_' + index;  //字符串拼接 id_username,id_password...
                            $(targetId).next().html(obj[0]).parent().addClass('has-error')
                        })
                    }
    
                }
            })
        });
        $('input').focus(function () {
            $(this).next().html('').parent().removeClass('has-error')
    
        })
    $('#myform').serializeArray()是form表单中的所有数据,自动获取form表单中所有input框键值对,用each循环取出来
    
    console.log($('#myform').serializeArray())

     post请求发送后端代码

    from django.shortcuts import render,HttpResponse
    from . import myforms
    from . import models
    from django.http import JsonResponse
    # Create your views here.
    
    #注册
    def register(request):
        back_dic = {'code':100,'msg':''}
        #实例化一个form对象
        form_obj = myforms.MyForm()
        if request.method == 'POST':
            form_obj = myforms.MyForm(request.POST)
            if form_obj.is_valid():
                # 拿到通过验证的用户信息字典,里面还有confirm_password
                cleaned_data = form_obj.cleaned_data
                # 由于创建用户不需要confirm_password这个字段,需要删除
                cleaned_data.pop('confirm_password')
                # 获取用户上传的头像文件
                file_obj = request.FILES.get('myfile')
                # 如果用户上传头像,则加入cleaned_data里并已通过创建到用户表里
                if file_obj:
                    cleaned_data['avatar'] = file_obj
                #因为我们需要创建的用户信息和值都在cleaned_data里面这里,cleaned_data又是一个字典,可以**打撒成?=?的方法传值
                # 注意的是前端的name的值必须跟数据库里的字段一直才可以**传值
                models.UserInfo.objects.create_user(**cleaned_data)
                back_dic['msg'] = '注册成功'
                back_dic['url'] = '/login/'
            else:
                back_dic['code'] = 101
                back_dic['msg'] = form_obj.errors
            # 因为给前端传的是字典,需要用JsonResponse
            return JsonResponse(back_dic)
        return render(request,'register.html',locals())
  • 相关阅读:
    Condtion type Z123 is mandatory!
    PUSU 拆分后发货和开票的时间节点问题
    mass create DN
    Mike Piehl
    变式配置简介 VARIANT CONFIGURATION
    4th Dec 2018
    (转)SQL Server 2012笔记分享-25:配置备份维护计划
    从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft.Server.manageDTS)
    SQL Server 2008 Tempdb 数据库迁移
    .woff HTTP GET 404 (Not Found)
  • 原文地址:https://www.cnblogs.com/zhengyuli/p/11054502.html
Copyright © 2011-2022 走看看