一、表分析
存在7张表 :
用户表UserInfo
站点表Blog
标签表Tag
分类表Category
点赞表 UpAndDown
评论表 Comment
文章表 Article
用户表 UserInfo
继承django自带的auth组件里的user 表
用户电话 phone
用户头像 avatar
创建时间 create_time
blog 一对一
站点表 Blog
站点名 name
标题 title
主题 theme 存放html样式
标签表Tag
标签名 name
blog 一对多
atricle 多对多 创建第三张表,可以实现添加字段的功能
分类表 Category
类名 name
blog 一对多
点赞表 UpAndDown
点赞与否 is_up
user 一对多
article 一对多
评论表 Comment
内容 content
评论时间 create_time
user 一对多
article 一对多
parent 对自己 考虑到对作者评论,对其他用户评论
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.BigIntegerField()
create_time = models.DateField(auto_now_add=True)
# 该字段会将接受到文件自动存放到avatar文件夹下,只存该文件的路径 比如:avatar/111.png
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=32)
# 站点的样式,存放其对应的文件路径
site_theme = models.CharField(max_length=64)
class Tag(models.Model):
name = models.CharField(max_length=16)
blog = models.ForeignKey(to='Blog', null=True)
class Category(models.Model):
name = models.CharField(max_length=16)
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()
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='Article_Tag', through_fields=('article', 'tag'))
class Article_Tag(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)
自定义form组件实现输入信息的初步校核
myform.py
from django import forms
from django.forms import widgets
from app01 import models
class MyForm(forms.Form):
username = forms.CharField(max_length=12, min_length=4, label='用户名',
widget=widgets.TextInput(attrs={'class': 'form-control'}), error_messages={
'max_length': '用户名长度最多不超过12位',
'min_length': '用户名长度最短不低于4位',
'required': '用户名不能为空'
})
password = forms.CharField(max_length=12, min_length=4, label='密码',
widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={
'max_length': '密码长度最多不超过12位',
'min_length': '密码长度最短不低于4位',
'required': '密码不能为空'
})
re_password = forms.CharField(max_length=12, min_length=4, label='确认密码',
widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={
'max_length' : '确认密码长度最多不超过12位',
'min_length': '确认密码长度最短不低于4位',
'required': '确认密码不能为空'
})
email = forms.EmailField(label='邮箱',widget=widgets.EmailInput(attrs={'class':'form-control'}) ,error_messages={
'required':'邮箱不能为空',
'invalid': '邮箱格式不正确'
})
phone = forms.IntegerField(label='手机号码',widget=widgets.PasswordInput(attrs={'class': 'form-control'}),error_messages={
'invalid':'请输入正确的手机号码',
'required':'手机号码不能为空'
})
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')
re_password = self.cleaned_data.get('re_password')
if password != re_password:
self.add_error('re_password','两次密码不一致!')
return self.cleaned_data
view.py 下的register
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
from app01 import myform
from app01 import models
from django.http import JsonResponse
def register(request):
back_dic = {'code':100,'msg':''}
form_obj = myform.MyForm()
if request.method == 'POST':
form_obj = myform.MyForm(request.POST)
if form_obj.is_valid():
data = form_obj.cleaned_data
#将re_password 去掉
data.pop('re_password')
#获取用户上传的文件对象
file_obj = request.FILES.get('myfile')
#判断用户是否上传了头像
if file_obj:
#往data里添加一组键值
data['avatar'] = file_obj
models.UserInfo.objects.create_superuser(**data)
back_dic['msg'] = '注册成功'
back_dic['url'] = '/login/'
else:
back_dic['code'] = 101
back_dic['msg'] = form_obj.errors
return JsonResponse(back_dic)
return render(request,'register.html',locals())
register.html
<!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 href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3" style="color: #4cae4c">
<h2 class="text-center">注册页面</h2>
<form novalidate id="myform" >
{% csrf_token %}
<div class="form-group">
{% for foo in form_obj %}
<label for="{{ foo.auto_id }}" style="margin-top: 10px">{{ foo.label }}</label>
{{ foo }}
<span class="error pull-right" style="color: #ff7090;margin-top: 10px" ></span>
{% endfor %}
</div>
</form>
<div class="form-group">
<label for="id_myfile">大头贴
<img src="/static/img/default.png" alt="" width="80px" style="margin-left: 20px" id="id_img">
</label>
<input type="file" name="myfile" id="id_myfile" style="display: none">
</div>
<button class="btn btn-success pull-right" id="id_submit">注册</button>
</div>
</div>
</div>
<script>
$('#id_myfile').change(function () {
{#获取上传的文件对象#}
let file_obj = this.files[0];
{#生成一个内置对象#}
let fileReader = new FileReader();
{#将文件对象传递给内置对象#}
fileReader.readAsDataURL(file_obj);
{#将读取出的文件对象替换到img标签#}
fileReader.onload = function () {
{#等待文件阅读器读取完毕再渲染图片#}
$('#id_img').attr('src',fileReader.result)
}
});
{#ajax提交数据#}
$('#id_submit').click(function () {
{#生成一个Formdata对象#}
let formData = new FormData();
{#往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 (datas) {
if (datas.code == 100){
{#跳到登陆页面#}
location.href = datas.url
}else{
$.each(datas.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')
})
</script>
</body>
</html>
初步效果: