0
点赞
收藏
分享

微信扫一扫

Django 博客

阿尚青子自由写作人 2022-03-25 阅读 69

1. 项目开发流程

1.1 需求分析

架构师 + 产品经理 + 开发者组长
在跟客户谈需求之前, 会大致先了解客户的需求, 然后先设计一套比较好写方案.
与客户沟通交流中引导客户往设计好方案上面靠, 形成一个初步的方案.

1.2 项目设计

架构师:
  	1. 编程语言选择
    2. 框架选择
    3. 数据库选择
    	3.1 主库:MySQL,postgreSQL,...
        3.2 缓存数据库:redis、mongodb、memcache...
    4. 功能划分
    	将整个项目划分成几个功能模块
    5. 组长开会
    	给每个组分发任务
   	6. 项目报价
    	技术这块需要多少人,多少天(一个程序员一天1500~2000计算(大致))
         产品经理公司层面, 公司财务签字确认, 公司老板签字确认 产品经理去跟客户沟通
     	后续需要加功能 继续加钱

1.3 分组开发

组长找组员开会,安排各自功能模块
组员在架构师设计好的框架里面填写代码,

在写代码的时候,需要自己先测试是否有bug,
如果是一些显而易见的bug, 没有避免而是直接交给了测试部门测出来...

1.4 测试

测试部门测试提交的代码
压力测试

1.5上线

1.交给对方的运维人员
2.直接上线到公司的服务器上 收取维护费用
3.其他...

2. 环境准备

前端 HTML + CSS + JavaScript
后端   Python 3.6
架构   Django 1.11.11
数据库 Mysql  5.6.47

2.1 新建Django项目

20220323194421

2.2 解决路径问题

项目名目录下的settings 第58行.    
	# 0. 修改静态文件路径已知Bug
    'DIRS': [BASE_DIR, 'templates']

2.3 建立bbs库

由于django自带的sqlite数据库对日期不敏感,所以我们换成MySQL.
使用Navicat创建bbs库.
数据库的名称 bbs 字符集 utf8mb4
# 命令行创建
CREATE DATABASE `bbs` CHARACTER SET 'utf8mb4';

20220323194134

2.4 Django连接MySQL

# 1. 数据配置文件
DATABASES = {
    'default': {
        # 1.0 输入的数据库引擎
        'ENGINE': 'django.db.backends.mysql',
        # 1.1 IP
        'HOST': '127.0.0.1',
        # 1.2 端口
        'POST': 3306,
        # 1.3 登入的用户名
        'USER': 'root',
        # 1.4 登入用户的密码
        'PASSWORD': 123,
        # 1.5 连接的库
        'NAME': 'bbs',
        # 1.6 字符编码
        'CHARSET': 'UTF8'
    }
}
在app01 应用下 __init__.py 中配置 pymysql 模块连接数据库.
import pymysql
pymysql.install_as_MySQLdb()

2.5 开放静态文件

0. 在项目目录下创建 static 静态文件目录.
1. 在static目录下 创建 js 目录, 将jQuery文件复制到 js 目录中.
2. 复制bootstarp框架文件到 static 目录中.
3. 去项目名文件下settings.py 中设置开放静态文件.

20220323200532

# settings.py 
STATIC_URL = '/static/'

# 2. 开放静态文件路径

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'STATIC')
]

2.6 访问测试

0. 启动项目
1. 在浏览器中输入: 127.0.0.1:8000

20220323201313

3. 表设计

一个项目中最重要的不是业务逻辑的书写
而是前期的表设计,只要将表设计好了,后续的功能书写才会一帆风顺.
在app01 下的 models.py 使用ORM模块, 创建映射表的类.
先写普通的字段, 在写外键字段.

3.1用户表 User

20220323122604

用户表: 记录用户的信息
继承AbstractUser 使用Auth模块
	
扩展字段:
    phone        用户电话号码    IntegerField 数值类型 大整数 用4位来表示 
    avatar       用户头像        FileField    文件类型
    create_time  用户创建时间     DateField    日期 年月日
 
外键字段: 
	用户表一对一个人站点表, 外键字段建在查询评论多的一方.
	blog        外键绑定个人博客表的id
from django.db import models

# Create your models here.

# 0. 用户表
# 0.1 导入 AbstractUser 类
from django.contrib.auth.models import AbstractUser


# 0.2 用户信息表   继承Auth表 拓展额外的字段
class UserInfo(AbstractUser):
    # 0.3 手机号 数值类型
    phone = models.IntegerField(null=True, verbose_name='手机号')
    # 0.4 头像 文件类型
    avatar = models.FileField(upload_to='avatar/', default='avatar/default.png', verbose_name='头像')
    # 0.5 用户创建时间   自动获取当前 年月日   (UTC 时间)
    create_time = models.DateField(auto_now_add=True, verbose_name='用户创建时间')
    # 0.6 外键字段 blog_id 关联 个人博客表id  在写表数据的时候可以不对此字段写数据
    blog = models.OneToOneField(to='Blog', null=True, verbose_name='关联博客表id')
# 项目名目录下 settings.py 
# 3. 配置 AUTH 模块使用的表
AUTH_USER_MODEL = 'app01.UserInfo'
avatar 字段存放的文件路径 avatar/xxx.pnh
upload_to='avatar/',           upload_to  参数 文本保存的位置, 
default='avatar/default.png'   用户不上床头像,使用 default 参数设置的默认头像.    
在项目下创建avatar目录, 找一个图片设置为 default.png 默认头像.

image-20220323203625318

3.2 个人博客表 Blog

个人博客/个人站点表: 记录每个用户个人网站, 访问时查询有没有该有户的个人站点存在.
每个人站点有自己的站点名称, 站点标题, 站点样式.
https://www.cnblogs.com/python

20220323122746

https://www.cnblogs.com/java

20220323122820

https://www.cnblogs.com/python_21

20220323123133

字段:
    site_name    站点名称   CharField  字符串类型
    site_title 	 站点标题   CharField  字符串类型
    site_theme	 站点样式   CharField  字符串类型
# 1. 个人博客表
class Blog(models.Model):
    # 1.0 id 字段自动生成
    # 1.1 站点名称
    site_name = models.CharField(max_length=32, verbose_name='站点名称')
    # 1.2 站点标题
    site_title = models.CharField(max_length=32, verbose_name='站点标题')
    # 1.3 站点样式 样式的路径
    site_theme = models.CharField(max_length=32, verbose_name='站点样式')
站点样式 字段存放css/js文件的路径, 简单的操作下样式的切换.

3.3 文章表 Article

文章表记录文字的内容.

20220323131027

字段:
    文章的标题   title          CharField   字符串类型
    文章简介     desc           CharField   字符串类型
    文章内容     content        TextField   文本字段适合存大量文本信息 不需要指定 max_length
    文章发布时间  create_time    DateField   日期 年月日
	
	查询优化:
	虽然下述的三个字段可以从其他表里面跨表查询计算得出,但是频繁跨表效率低下,
	直接在文章表中创建三个普通的字段, 点赞点踩, 评论表, 记录数据的时候同步文章表的这三个字段.
	
    文章的点赞数   up_num        BigIntegerField    极大整数值 用8位表示
    文章的点踩数   down_num      BigIntegerField    极大整数值 用8位表示
    文字的评论数   comment_num   BigIntegerField    极大整数值 用8位表示

    * 访问数不做, 换为点踩.

外键字段:
	站点表      一对多    文章表   外键    blog_id 绑定站点表的id
	文章标签表  多对多    文章表   虚拟字段 tag  半自动建立第三张表
	文章分类表  一对一    文章表	外键   sort_id 绑定分类表id  

# 2. 文章表
class Article(models.Model):
    # 2.1 id 字段自动生成
    # 2.2 文章标题
    title = models.CharField(max_length=32, verbose_name='标题')
    # 2.3 文章简介
    desc = models.CharField(max_length=256, verbose_name='简介')
    # 2.4 文章内容 
    content = models.TextField(verbose_name='文章内容')
    # 2.5 文章创建时间 创建文章的时候会自动获取UTC时间
    create_time = models.DateField(auto_now_add=True, verbose_name='文章创建时间')

    # 数据库的字段优化
    # 2.6 点赞数
    up_num = models.BigIntegerField(default=0, verbose_name='点赞数')
    # 2.7 点踩数
    down_num = models.BigIntegerField(default=0, verbose_name='点踩数')
    # 2.8 评论数
    comment_num = models.BigIntegerField(default=0, verbose_name='评论数')
    # 2.9 外键 blog_id 关联 博客表的id
    blog = models.ForeignKey(to='Blog', null=True, verbose_name='关联博客表id')
    # 2.10 外键 sort_id 关联分类表id
    sort = models.OneToOneField(to='Sort', null=True, verbose_name='关联分类表id')
    # 2.11 虚拟字段端 半自动创建第三张表
    tag = models.ManyToManyField(to='Tag', through='ArticleToTag',
                                 # 第三张表中 article字段与tag字段关联
                                 through_fields=('article', 'tag'))
# 7. 文章表多对多标签表的第三张表
class ArticleToTag(models.Model):
    # 7.1 id字段自动生成
    # 7.2 外键 article_id 绑定 文章表的id
    article = models.ForeignKey(to='Article')
    # 7.2 外键 tag_id 绑定 标签表的id
    tag = models.ForeignKey(to='Tag')

3.4 文章的标签 Tag

一个文章可以打上很多个标签.
字段:
	标签的名字  name   CharField  字符串类型
	
外键字段: (这个字段存在的原因是需要在个人博客表中,侧边栏可以通过标签去查找对应的文章)
	个人站点表 一对多 文章标签表
	blog_id 绑定博客表的id
# 3. 标签表
class Tag(models.Model):
    # 3.1 id 字段自动生成
    # 3.2 标签名称
    name = models.CharField(max_length=32, verbose_name='文章标签')
    # 3.3 外键
    blog = models.ForeignKey(to='Blog', null=True, verbose_name='绑定博客表的id')

3.5 文章的分类 Sort

一个文章属于一个类型.(一个文章就一个类, 不搞多个.)

字段:
	类的名字 name   CharField  字符串类型
	
外键字段:(这个字段存在的原因是需要在个人站点中, 侧边栏可以通过分类去查找对应的文章)
	个人站点表 一对多 文章分类表
	blog_id 绑定博客表的id
# 4. 分类表
class Sort(models.Model):
    # 4.1 id 字段自动生成
    # 4.2 分类的名称
    name = models.CharField(max_length=32, verbose_name='文章分类')
    # 4.3 外键 blog_绑定 博客表的id
    blog = models.ForeignKey(to='Blog', null=True, verbose_name='绑定博客表的id')

3.6 点赞点踩表 UpAndDown

文章点赞点踩表: 记录那个用户给哪篇文章点了赞还是点了踩
字段:
	用户名        user
	文章名        article
    点赞/点踩      is_up

20220323132450

id    user_id    article_id    is_up
1        1           1           1         用户1 给第一篇文章点了赞
2        2           1           1         点赞 统计 article的 is_up 为1 数量
3        3           1           1         点踩 统计 article的 is_up 为1 数量
# 5. 点赞点踩表
class UpAndDown(models.Model):
    # 5.1 id 字段自动生成
    # 5.2 外键 user_id    关联用户id  _id自动增加
    user = models.ForeignKey(to='UserInfo', verbose_name='关联用户id')
    # 5.3 外键 article_id  关联文章id _id自动增加
    article = models.ForeignKey(to='Article', verbose_name='关联文章id')
    # 5.4 是否点赞  布尔值 存的是0/1
    is_up = models.BooleanField(verbose_name='是否点赞')

3.7 文字评论表 Comment

文章的评论表: 记录那个用户给哪篇文字评论了什么内容

字段: 
	用户名    user
	文章名    article
	评论内容  content
	评论时间  comment_time
根评论子评论的概念
	根评论就是直接评论当前发布的内容的
		
	子评论是评论别人的评论
		1.PHP是世界上最牛逼的语言
			1.1 PHP是世界上最牛逼的语言.py
				1.1.1 java才是.py
				1.2.1 go才是.py
		
根评论与子评论是一对多的关系
自关联
parent					ForeignKey(to="Comment",null=True)		
ORM专门提供的自关联写法	
parent					ForeignKey(to="self",null=True)
id	user_id    article_id    parent_id
1	 1		      1			(可以不评论)						
2    2			  1				1 (代表这个评论是给这个表第一个内容的)		

20220323132417

# 6. 评论表
class Comment(models.Model):
    # 6.1 id字段自动生成
    # 6.2 外键  user_id     关联用户id  _id自动增加
    user = models.ForeignKey(to='UserInfo', verbose_name='关联用户id')
    # 6.3 外键 article_id  关联文章id _id自动增加
    article = models.ForeignKey(to='Article', verbose_name='关联文章id')
    # 6.4 评价内容
    content = models.CharField(max_length=256, verbose_name='评价内容')
    # 6.5 评论时间 年月日 时分秒 UTC 时间
    comment_time = models.DateTimeField(auto_now_add=True, verbose_name='评论时间')

    # 6.6 自关联 parent_id关联这张表的id
    parent = models.ForeignKey(to='self', null=True, verbose_name='自关联')
只要关联了就代表它是子评论, 否则就是根评论, null=True, 不写就只能是评论了

image-20220323225818564

3.8数据库迁移

python manage.py makemigrations
python manage.py migrate

image-20220324024036996

4. 用户注册功能

4.1 路由层

from django.conf.urls import url
from django.contrib import admin
# 0. 导入 视图层
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 1. 注册功能
    url(r'^register/', views.register)
]

4.2 forms组件

0. 在app01应用程序下创建 forms_module 目录
1. 在 forms_module 目录下创建 register_froms.py 文件
# 0. 导入 forms 组件
from django import forms
# 1. 导入 models 模型层
from app01 import models


# 1. 创建注册表forms组件 继承 forms.Form
class RegisterForms(forms.Form):
    # 1.1 名称
    username = forms.CharField(
        # 展示名称, 限制
        label='名称', min_length=3, max_length=8,
        # 错误信息
        error_messages={
            'required': '名称不能为空',
            'min_length': '名称不能少于3位',
            'max_length': '名称不能超过8位'},
        # 样式 input框 border:none 无边框  background-color:transparent; 背景颜色透明 字体颜色
        widget=forms.widgets.TextInput(
            attrs=(
            {'class': 'form-control input-lg', 'style': 'border:none; background-color:transparent; color: #66AFE9;'})
        )
    )

    # 1.2 密码
    password = forms.CharField(
        # 展示名称, 限制
        label='密码', min_length=3, max_length=8,
        # 错误信息
        error_messages={
            'required': '密码不能为空',
            'min_length': '密码不能少于3位',
            'max_length': '密码不能超过8为'},
        # 样式
        widget=forms.widgets.PasswordInput(
            attrs=(
            {'class': 'form-control input-lg', 'style': 'border:none; background-color:transparent; color: #ffaa00;'})
        )
    )

    # 1.3 确定密码
    confirm_password = forms.CharField(
        # 展示名称, 限制
        label='确认密码', min_length=3, max_length=8,
        # 错误信息
        error_messages={
            'required': '确认密码不能为空',
            'min_length': '确认密码不能少于3位',
            'max_length': '确认密码不能超过8位'},
        # 样式
        widget=forms.widgets.PasswordInput(
            attrs={'class': 'form-control input-lg',
                   'style': 'border:none; background-color:transparent; color: #ffaa00;'}
        )
    )

    # 1.4 邮箱
    email = forms.EmailField(
        # 展示名称
        label='邮箱',
        # 错误信息
        error_messages={
            'required': '邮箱不能为空',
            'invalid': '邮箱格式不正确'},
        # 样式
        widget=forms.widgets.EmailInput(
            attrs=(
            {'class': 'form-control input-lg', 'style': 'border:none; background-color:transparent; color: #ffaa00;'})
        )
    )

    # 1.5 局部钩子 判断用户名是否存在
    def clean_username(self):
        # 1.5.1 获取用户名
        username = self.cleaned_data.get('username')
        # 1.5.2 去用户表中匹配数据
        is_exist = models.UserInfo.objects.filter(username=username)

        # print(is_exist)
        # 用户不存在显示 <QuerySet []>

        # 1.5.3 判断返回的数据 如果存在
        if is_exist:
            self.add_error('username', '名称已经存在')

        # 1.5.4 返回钩子函数
        return username

    # 1.6 全局钩子 判断两次密码是否一致
    def clean(self):
        # 1.6.1 获取密码
        password = self.cleaned_data.get('password')
        # 1.6.2 获取确认密码
        confirm_password = self.cleaned_data.get('confirm_password')
        # 1.6.3 判断是否一致
        if password != confirm_password:
            # 1.6.4 添加错误提示信息
            self.add_error('confirm_password', '两次密码不一致')

        # 1.6.6 返回全局钩子
        return self.cleaned_data

4.3 视图层

# 0. 导入django 三板斧
from django.shortcuts import render, redirect, HttpResponse

# 1.导入 注册表单forms组件
from app01.forms_module.register_forms import RegisterForms


# 2.注册功能
def register(request):
    # 2.0 生成 forms组件对象
    forms_obj = RegisterForms()

    # 2.1 返回注册页面 与 forms组件对象
    return render(request, 'register.html', locals())

4.4 模板层

在templates目录下创建 register.html
form表单 autocomplete="off" 浏览器不自动填充数据.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <!--0. 动态获取静态文件路径-->
    {% load static %}
    <!--1. 导入 jQuery js文件 -->
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    <!--2. 导入 bootstrap css 文件-->
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <!--3. 导入 bootstrap js 文件-->
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>

    <style>
        /* 13. body背景设置 */
        body {
            /* 网页背景 */
            background-image: url("{% static 'background/register.jpg'%}");
            /*  不缩放  */
            background-size: cover;
            /*  不平铺  */
            background-repeat: no-repeat;
            /* 字体颜色 */
            color: #d4ff00;
            font-size: 18px;
        }

        /* 14. 自动填充值不留白 */
        input:-webkit-autofill,
        input:-webkit-autofill:hover,
        input:-webkit-autofill:focus,
        input:-webkit-autofill:active {
            -webkit-transition-delay: 111111s;
            -webkit-transition: color 11111s ease-out, background-color 111111s ease-out;
        }
    </style>

</head>
<body>
<!--4. .container-fluid 类用于 100% 宽度,占据全部视口(viewport)的容器。-->
<div class="container-fluid">
    <!--5. 栅格系统-->
    <div class="row">
        <!-- 占8格 右移2格-->
        <div class="col-md-6 col-md-offset-3">
            <!--6. 标题-->
            <h1 class="text-center">注册</h1>
            <!--7. 表单 autocomplete="off" 不自动填充数据 -->
            <form action="" autocomplete="off" id="form_table">
                <!--8. csrf 校验 -->
                {% csrf_token %}
                {% for input in forms_obj %}
                    <div class="form-group">
                        <!-- auto_id 自动获取input的id属性  -->
                        <label for="{{ input.auto_id }}">{{ input.label }}</label>
                        {{ input }}

                        <!--pull-right 在右边显示 -->
                        <span style="color: red; " class="pull-right"></span>
                    </div>
                {% endfor %}
                <!--8. 头像 文件类型-->
                <label for="my_avatar">头像
                    <img src="{% static 'img/default.png' %}" alt="" id='my_img' width="80px" style="margin-left:20px">
                </label>

                <input type="file" name="avatar" id="my_avatar" style="display: none">

                <!--9. Ajax按钮 button按钮不会提交form表单的数据 按钮属性不要加btn 不然点按钮有白边不好看-->
                <p>
                    <input type="button" id='btn1' value="注册" class="btn-primary btn-lg btn-block"
                           style="border: none; opacity:0.3; color: orange; font-size: 20px">
                </p>

            </form>
        </div>
    </div>
</div>
<script>
    // 10. 绑定文本域变化事件  文本阅读器对象, 将上传的头像文件用阅读器获取出来
    $('#my_avatar').change(function () {
        // 10.1 生成一个文本器阅读对象
        let FileReaderObj = new FileReader()

        // 10.2 获取用户上传的文件  (this)[0]对象转为  DOM对象  files[0]取文件值
        let UpFileObj = $(this)[0].files[0];

        // 10.3 将文件对象交给阅读器对象读取
        FileReaderObj.readAsDataURL(UpFileObj)  // 异步操作, IO操作

        // 10.4 绑定加载事件 等待文件阅读完毕之后再执行事假 修改img标签的值
        FileReaderObj.onload = function () {
            // 10.5 attr标签属性值 属性   值(人本阅读器的结果)
            $('#my_img').attr('src', FileReaderObj.result)
            console.log(FileReaderObj.result)
        }

    })

    // 11. 绑定点击事件 获取表单数据 使用ajax提交表单数据
    $('#btn1').on('click', function () {
        // 11.1 创建一个表单对象
        let FormDataObj = new FormData()

        // 11.2 获取form表单的所有文本数据
        let Text_Data = $('#form_table').serializeArray()

        // console.log(Text_Data)
        // 获取的数据是列表套字典 [{'name': '表单name值', 'value': '表单value值'}, {}, {}]


        // 11.3 遍历form表单的文本数据 添加到表单对象中 each(可迭代的值, 函数(索引, 索引对应的值){})
        $.each(Text_Data, function (index, obj) {

            // console.log(index, obj)
            //  0 {name: 'username', value: 'kid'} ...

            // 11.4 添加数据到 表单对象中
            FormDataObj.append(obj.name, obj.value)
        })

        // 11.5 表单对象添加文件对象
        FormDataObj.append('avatar', $('#my_avatar')[0].files[0])

        // 11.6 发送ajax请求
        $.ajax({
            // 11.6.1 提交地址
            url: '',
            // 11.6.2 提交方式
            type: 'post',
            // 11.6.3 上传的数据
            data: FormDataObj,

            // 11.6.4 上传文件必须设置的参数
            contentType: false,  //  不需要任何编码django能自动识别表单对象
            processData: false,  // 告诉浏览器不要对数据进行任何处理

            // 11.6.5 回调函数
            success: function (args) {
                // 11.6.6 判断 状态码
                if (args.code === 200) {
                    // 11.6.7 用户注册成功后, 跳转网页  http://127.0.0.1:8000/login/
                    window.location.href = args.url


                } else {

                    // console.log(args.error)
                    // {username: Array(1)..)}  confirm_password: ['确认密码不能为空']... 一个大字典 each 将 k:v 传递给函数

                    // 11.6.8 在input框后面的span后面展示错信息
                    $.each(args.error, function (key, value) {

                        console.log(key, value)
                        // confirm_password ['确认密码不能为空']

                        // 11.6.9 获取input标签 input的id 优 forms组件创建, 他的id值特点是 id='id_name值'
                        let InputId = '#id_' + key
                        // 11.6.10 移除 input框的 border属性值 将 border: none 移除 展示出边框
                        $(InputId).css('border', '')
                        // 11.6.11 input后面的标签添加错误提示信息, 它的父标签添加一个样式 红色边框 has-error input框变红色 链式擦操作
                        $(InputId).next().text(value[0]).parent().addClass('has-error')
                    })

                }
            }

        })
    })

    // 12. 绑定获取焦点事假
    $('input').focus(function () {
        // 12.1 清除 错误信息和input款的颜色
        $(this).next().text('').parent().removeClass('has-error')
        // 12.2 input框添加 border属性值 设置为没有边框
        $(this).css('border', 'none')
    })
</script>
</body>
</html>

        // 11.2 获取form表单的所有文本数据
        let Text_Data = $('#form_table').serializeArray()

image-20220325092806468

each遍历列表获取到两个参数,第一个是index索引, 第二个是索引对应的值.
        // 11.3 遍历form表单的文本数据 添加到表单对象中 each(可迭代的值, 函数(索引, 索引对应的值){})
        $.each(Text_Data, function (index, obj) {
                     console.log(index, obj)...

image-20220325092452231

// ajax接收 后端返回 检验不通过的数据
args.error

image-20220325092942973

each遍历对象获取到两个参数,第一个是属性, 第二个是属性值
                    // 11.6.8 在input框后面的span后面展示错信息
                    $.each(args.error, function (key, value) {
                        console.log(key, value) ...

image-20220325093205739

forms组件 表单错误信息提示

image-20220325095653515

image-20220325095818909

4.5 业务逻辑

# 0. 导入django 三板斧
from django.shortcuts import render, redirect, HttpResponse

# 1.导入 注册表单forms组件
from app01.forms_module.register_forms import RegisterForms

# 2.9 时 导入models 模型
from app01 import models

# 2.11 事 导入 JsonResponse
from django.http import JsonResponse


# 2.注册功能
def register(request):
    # 2.0 生成 forms组件对象
    forms_obj = RegisterForms()
    # 2.2 判断请求方式
    if request.is_ajax():
        # 2.3 检验数据是否合法
        forms_obj = RegisterForms(request.POST)

        # 2.4 如果数据合法
        if forms_obj.is_valid():
            # 2.5 获取所有合法数据 赋值给一个变量 是一个字典
            cleaned_data = forms_obj.cleaned_data

            # print(cleaned_data)
            # {'username': 'kid', 'password': '123', 'confirm_password': '123', 'email': '1360012768@qq.com'}

            # 2.6将 confirm_password的数据弹出
            cleaned_data.pop('confirm_password')

            # 2.7 获取文件数据
            avatar_obj = request.FILES.get('avatar')

            # print(avatar_obj)
            # 如果没有自己选头像获取到 None  选了头像 文件对象 头像1.png

            # 2.8 判断头像是否为空
            if avatar_obj:
                cleaned_data['avatar'] = avatar_obj

            # 2.9 写入数据
            models.UserInfo.objects.create_user(**cleaned_data)
            print('写入数据成功!')

            # 2.10 数据写入成功后 返回的数据 状态码200 跳转的页面, 格式一定要是 /login/
            back_dir = {'code': 200, 'url': '/login/'}

        else:
            # 2.11 数据检验不合法 返回的数据  状态码400 错误的提示信息
            back_dir = {'code': 400, 'error': forms_obj.errors}

            # print(forms_obj.errors)
            # 错误的信息 <ul class="errorlist"><li>confirm_password<ul class="errorlist"><li>两次密码不一致</li></ul></li></ul>

        # 2.12  返回json格式数据 返回一个字典数据给ajax, 前端拿到的就一个对象
        # print(back_dir)
        return JsonResponse(back_dir)

    # 2.1 返回注册页面 与 forms组件对象
    return render(request, 'register.html', locals())
举报

相关推荐

0 条评论