仿BBS之注册

模仿BBS的注册功能,先谈一谈项目需求分析

项目分析
表设计
用户表(UserInfo)
用户电话phone
用户头像avatar
用户创建时间create_time


blog 》》》site 一对一个人站点表

个人站点表(Blog)
站点名称site_name
站点标题site_title
站点样式site_theme

文章标签表(Tag)
标签名称name
blog >>> Blog 一对多个人站点表

文章分类表
分类名称name
blog >>> Blog 一对多个人站点表

文章表
文章标题title
文章简介desc
文章详情content
文章发布时间create_time
# 数据库查询优化
文章评论数comment_num
文章点赞数up_num
文章点踩数down_num

blog 》》》 Blog 一对多个人站点表
tags >>> Tag 多对多标签表
category 》》》 Category 一对多分类表

点赞点踩表
用户名字段user 一对多 个人站点/用户
文章字段article 一对多 文章表
点赞点踩is_up 0/1

文章评论表
用户名字段user 一对多 个人站点/用户
文章字段article 一对多 文章表
评论内容content
父评论parent(自己跟自己关联) 一对多自身

models.py文件

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

class UserInfo(AbstractUser):
    phone = models.BigIntegerField(null=True)
    create_time = models.DateField(auto_now_add=True)
    avatar = models.FileField(upload_to='avatar/',default='avatar/default.png')
    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=64)
    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=64)
    desc = models.CharField(max_length=255)
    content = models.TextField()
    create_time = models.DateField(auto_now_add=True)
    comment_num = models.IntegerField()
    up_num = models.IntegerField()
    down_num = models.IntegerField()
    blog = models.ForeignKey(to='Blog',null=True)
    category = models.ForeignKey(to='Category',null=True)
    tags = models.ManyToManyField(to='Tag',through='Article2Tags',through_fields=('article','tag'))


class Article2Tags(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)
    create_time = models.DateField(auto_now_add=True)
    parent = models.ForeignKey(to='self',null=True)

我们使用forms组件来限制前后端数据的传输

forms.py文件

from django import forms
from django.forms import widgets
from app01 import models

class MyForm(forms.Form):
    username = forms.CharField(max_length=8,min_length=3,label='用户名:',error_messages={
        'required':'用户名不能为空',
        'max_length':'用户名最长8位',
        'min_length':'用户名最短3位',
    },widget = widgets.TextInput(attrs={'class':'form-control'}))
    password = forms.CharField(max_length=8,min_length=3,label='密码',error_messages={
        'required':"密码不能为空",
        'max_length':'密码最长为8位',
        'min_length':'密码最短为3位',

    },widget =forms.widgets.PasswordInput(attrs={'class':'from-control'}))
    confirm_password = forms.CharField(max_length=8,min_length=3,label='确认密码',error_messages={
        'required':'确认密码不能为空',
        'max_length':'确认密码最大8位',
        'min_length':'确认密码最小3位'
    },widget =widgets.PasswordInput(attrs={'class':'form-control'}))
    email = forms.EmailField(label='邮箱',error_messages={
        'required':'邮箱不能为空',
        'invalid':'邮箱格式序错误',
    },widget=forms.widgets.EmailInput(attrs={'class':'form-control'}))
    def clean_username(self):
        username = self.cleaned_data.get('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

使用views.py视图函数来对路由过来的路径进行匹配执行

from django.shortcuts import render
from app01 import myforms
from app01 import models
from django.http import JsonResponse

# Create your views here.
def register(request):
    back_dic= {'code':100,'msg':''}
    form_obj = myforms.MyForm()
    if request.method =='POST':
        form_obj =myforms.MyForm(request.POST)
        if form_obj.is_valid():
            data = form_obj.cleaned_data
            data.pop('confirm_password')
            file_obj = request.FILES.get('myfile')
            if file_obj:
                data['avatar']= file_obj
            models.UserInfo.objects.create_user(**data)
            back_dic['msg']='注册成功'
            back_dic['url']='/login/'
        else:
            back_dic['code']=101
            back_dic['mag']=form_obj.errors
        return JsonResponse(back_dic)
    return render(request,'register.html',locals())

我们不妨来看看前端页面经过渲染是什么样子吧

其实对于用户名,密码以及确认密码和邮箱这种键值对来说我们用ajax来进行交互式时,只是常规操作

对于头像,我们该怎么如何进行传输呢?

$('#d1').click(function () {
        $.ajax({
            // 提交的地址,不写默认提交至当前页面,同form表单的action
            url:'/index/',
            // 提交的方式
            type:'post',
            // 提交的数据,一般以键值对的形式出现
            data:{'name':'jason','password':'123'},
            // 回调函数
            success:function (data) {  // data接收的就是异步提交返回的结果
                alert(data)
            }
        })
    })

这是常规操作

<!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>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <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/img/default.png" alt="" width="80" style="margin-left: 20px" id ='id_img'>
                </label>
                <input type="file" name="myfile" id="id_myfile" style="display:none">
            </div>
            <button class="btn btn-primary pull-right" id="id_submit">注册</button>
        </div>
    </div>

</div>

<script>
    $('#id_myfile').change(function () {
        let fileObj = this.fiels[0];
        let fileReader= new FileReader()
        fileReader.readAsDataURL(fileObj);
        fileReader.onload = function () {
            $('#id_img').attr('src',fileReader.result)
        }
    });
    $('#id_submit').click(function () {
        let formData = new FormData();
        $.each($('#myform').serializeArray(),function (index, obj) {
            formData.append(obj.name, obj.value)
        });
        formData.append('myfile',$('id_myfile')[0].files[0]);
        $.ajax({
            url:'',
            type:'post',
            data:formData,
            processData:false,
            contentType:false,
            success:function(data){
                if (data.code==100){
                    location.href=data.url
                }else{
                    $.each(data.msg,function (index,obj) {
                        let targetId ='#id_'+index;
                        $(targetId).next().html(obj[0].parent().addClass('has-error'))
                    })
                }
            }

        })
    });
    $('input').focus(function () {
        $(this).next().html('').parent().removeClass('has-error')
    })
</script>




</body>
</html>

这是经过Javascript的处理后端h5文件

在写一个注册页面时,想要实现用户选择头像时,直接就能将选择的头像显示出来,就必须使用到JS的FileReader对象。

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。 其中File对象可以是来自用户在一个元素上选择文件后返回的FileList对象(上面提到的使用files属性得到的文件对象),也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果

 可以用window对象的方法查看浏览器对FileReader的支持

if(window.FileReader) {
     var fr = new FileReader();
     // add your code here
 }
 else {
     alert("Not supported by your browser!");
 }
承蒙关照
原文地址:https://www.cnblogs.com/guanlei/p/11055744.html