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>