BBS之注册与登录

settings.py

 1 # 在项目中要使用到mysql,所以先在settings文件中完成对mysql数据库的配置。
 2 DATABASES = {
 3     'default': {
 4         'ENGINE': 'django.db.backends.mysql',
 5         'NAME': 'bbs',
 6         'USER':'root',
 7         'PASSWORD':'123',
 8         'HOST':'127.0.0.1',
 9         'PORT':3306
10     }
11 }
12 
13 STATIC_URL = '/static/'
14 STATICFILES_DIRS = [
15     os.path.join(BASE_DIR,'static')   # 配置静态文件
16 ]
17 
18 AUTH_USER_MODEL = 'app01.UserInfo'  #

# 在跟settings文件处于同一级别的__init__文件中,完成导入pymysql的配置。
import pymysql
pymysql.install_as_MySQLdb()
 

myforms.py

 1 from django import forms
 2 from django.forms import widgets
 3 from app01 import models
 4 
 5 
 6 class MyRegForm(forms.Form):
 7     username = forms.CharField(max_length=8, min_length=3, label='用户名',
 8                                error_messages={
 9                                    'max_length': '用户名最大八位',
10                                    'min_length': '用户名最小三位',
11                                    'required': '用户名不能为空'
12                                }, widget=widgets.TextInput(attrs={'class': 'form-control'})
13                                )
14     password = forms.CharField(max_length=8, min_length=3, label='密码',
15                                error_messages={
16                                    'max_length': '密码最大八位',
17                                    'min_length': '密码最小三位',
18                                    'required': '密码不能为空'
19                                }, widget=widgets.PasswordInput(attrs={'class': 'form-control'})
20                                )
21     confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码',
22                                        error_messages={
23                                            'max_length': '确认密码最大八位',
24                                            'min_length': '确认密码最小三位',
25                                            'required': '确认密码不能为空'
26                                        }, widget=widgets.PasswordInput(attrs={'class': 'form-control'})
27                                        )
28     email = forms.EmailField(label='邮箱', error_messages={
29         'required': "邮箱不能为空",
30         'invalid': "邮箱格式错误"
31     }, widget=widgets.EmailInput(attrs={'class': 'form-control'}))
32 
33     # 局部钩子 校验用户名是否已存在
34     def clean_username(self):
35         username = self.cleaned_data.get('username')
36         is_user = models.UserInfo.objects.filter(username=username)
37         if is_user:
38             self.add_error('username', '用户名已存在')
39         return username
40 
41     # 全局钩子 校验密码是否一致
42     def clean(self):
43         password = self.cleaned_data.get('password')
44         confirm_password = self.cleaned_data.get('confirm_password')
45         if not password == confirm_password:
46             self.add_error('confirm_password', '两次密码不一致')
47         return self.cleaned_data

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserInfo(AbstractUser):    # 千万不能放AbstractUser表里有的字段
    phone = models.BigIntegerField(null=True)   # null=True表示该项可以不填写
    # avatar存的是用户头像文件路径 用户上传的头像会自动保存到avatar文件夹下
    avatar = models.FileField(upload_to='avatar/',default='avatar/default.jpg')
    create_time = models.DateField(auto_now_add=True)   # 注册时间

    blog = models.OneToOneField(to='Blog',null=True)    ## 与个人站点处于一对一关系


class Blog(models.Model):    # 个人站点表
    site_title = models.CharField(max_length=32)    # 站点名称
    site_name = models.CharField(max_length=32)     # 站点名字
    site_theme = models.CharField(max_length=255)   # 用来存css的文件路径


class Category(models.Model):    # 标签表
    name = models.CharField(max_length=32)
    blog = models.ForeignKey(to='Blog')    # 与个人站点处于一对多关系


class Tag(models.Model):    # 分类表
    name = models.CharField(max_length=32)
    blog = models.ForeignKey(to='Blog')    # 与个人站点处于一对多关系


class Article(models.Model):    # 文章表
    title = models.CharField(max_length=255)
    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)
    tag = 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()  # 传布尔值  存0/1  用来记录是点赞还是点踩

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)    # 字关联字段

register.html文件

 1 <body>
 2 <div class="container">
 3     <div class="row">
 4         <div class="col-md-8 col-md-offset-2">
 5             <h2 class="text-center">注册</h2>   {# 将'注册'进行居中处理 #}
 6             <form id="myform" novalidate>
 7                 {% csrf_token %}
 8                 {% for foo in form_obj %}  {# 直接for循环 #}
 9                     <div class="form-group">
10                         {#foo.auto_id获取foo渲染的input框的id值#}
11                         <label for="{{ foo.auto_id }}">{{ foo.label }}</label>
12                         {{ foo }}
13                         <span class="errors pull-right" style="color: red;"></span>
14                     </div>
15                 {% endfor %}
16                 <div class="form-group">    {# form-group用来处理输入框之间的间隙 #}
17                     <label for="myfile">头像  {# 获取头像,通过input框  #}
18                     <img src="/static/img/default.jpg" alt="" height="80" style=" margin-left: 20px" id="img">{# 将img放入label框中,点击图片也可以进行文件选择  margin-left用来调节头像与图片之间的距离#}
20                     </label>
21                     <input type="file" name="avatar" id="myfile" style="display: none">
22                 </div>
23                 <input type="button" class="btn btn-primary pull-right" value="注册" id="id_submit">
24             </form>
25         </div>
26     </div>
27 </div>
28 
29 <script>
30     $('#myfile').change(function () {
31         // 获取用户上传的头像 然后替换到img标签中
32         // 1 获取用户上传的文件对象
33         var fileObj = $(this)[0].files[0];
34         // 2.利用内置对象FileReader
35         var fileReader = new FileReader();  //文件阅读器
36         // 3.将文件对象交由文件阅读器读取 文件内容
37         fileReader.readAsDataURL(fileObj);  // IO操作速度较慢,异步
38         // 4.找到img标签 修改src属性
39         // 等待文件阅读器完全读取完文件数据之后 才做下面的操作 onload
40         fileReader.onload = function(){ $('#img').attr('src',fileReader.result)}
41     });
42 
43     // 绑定点击事件
44     $('#id_submit').click(function () {
45         // 1. 产生内置对象formdata
46         var formData = new FormData();
47         // 2. 循环添加普通键值对
48         {#console.log($('#myform').serializeArray())#}
49         $.each($('#myform').serializeArray(),function (index,obj) {
50             formData.append(obj.name,obj.value)
51         });
52         // 3. 手动添加文件
53         formData.append('myfile',$('#myfile')[0].files[0]) ;
54         // 4. 发送ajax请求
55         $.ajax({
56             url:'',     {# url不写,默认往当前页面发送 #}
57             type:'post',
58             data:formData,
59 
60             // 传文件需要指定两个参数
61             contentType:false,
62             processData:false,
63 
64             success:function (data) {
65                 if (data.code==100){
66                     location.href = data.url
67                 }else{
68                     // 如果没有成功 说明用户输入的数据不合法 你需要展示错误信息
69                     // console.log(data.msg)
70                     // 能够将对应的错误信息准确无误的渲染到对应的input下面的span标签中
71                     // 手动拼接input的id值
72                     $.each(data.msg,function (index,obj) {
73                         {#console.log(index,obj)#}
74                         var targetId = '#id_' + index;
75                         $(targetId).next().text(obj[0]).parent().addClass('has-error')
76                     })
77                 }
78             }
79         })
80     });
81 
82     $('input').focus(function () {
83         $(this).next().text('').parent().removeClass('has-error')
84     })
85 </script>
86 </body>
原文地址:https://www.cnblogs.com/blue-tea/p/11595640.html