1206 BBS注册
昨日内容
昨日内容
基于django中间件实现功能的插拔式设计
1.设计思想
2.自己记下来
跨站请求伪造csrf
1.出处
2.如何实施
django里面校验csrf是由中间件执行的csrf...
提交post请求如何通过csrf校验
form表单
只需要在form表单内写一句话
{% csrf_token %}
ajax
方式1
自己在data参数里面加上键值对
data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()}
方式2
利用模板语法
data:{'csrfmiddlewaretoken':'{{ csrf_token }}' }
# 前端参数如果没有起作用 你可以尝试着给参数加一个引号
方式3
利用官方提供的js代码
拷贝代码放入一个js文件中 你字需要在html页面上导入该js文件
之后你就不需要手动操作任何csrf相关的代码
# 拷贝到你们的本地
相关的装饰器
csrf_protect
csrf_exempt
# FBV中跟普通的装饰器一模一样
# CBV中csrf_exempt这个装饰器只能给dispatch方法装 csrf_protect还是正常的跟普通的装饰器一样
开发者笔记
xxx公司
问题 解决
同在一个屋檐下
为何差距那么大
上课都是认真听讲
每晚九点半之后
周末时间
看视频是最low的复习方式
auth模块
基于auth_user表 类似于一张已经提前创建好的用户表
from django.contrib import auth
from django.contrib.auth.models import User
1.创建用户
# create() 密码存的是明文的
create_user()
craete_superuser()
2.如何判断用户名和密码是否正确
user_obj = auth.authenticate(username=jason,password=123)
3.如何保存用户登录状态
auth.login(request,user_obj) # 只要执行了这句话 在任意位置都可以通过request.user获取到当前登录的用户对象
# 自动帮你操作session表
4.如何判断当前用户是否登录
request.user.is_authenticated()
5.校验密码是否正确
request.user.check_password(old_password)
6.修改密码
request.user.set_password(new_password)
request.user.save() # 一定要执行
7.注销
auth.logout(request)
8.校验登录装饰器
# 局部的
login_required(login_url='/login/')
# 全局的
LOGIN_URL = '/login/'
login_required
# 如果都配置了 按照局部的为准
如何扩展auth_user表
方式1 利用表与表之间的一对一的关系
方式2 利用面向对象的继承
1.在models中写一个模型类继承AbstractUser
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
phone = ...
avatar = ...
# 不要与原先的表中的字段冲突
2.一定要去配置文件中 指定你自己的表作为auth模块的基表
AUTH_USER_MODEL = 'app01.Userinfo'
django settings源码及实际应用
1.逻辑思路是什么
2.反射(******) + importlib模块
一切皆对象
def func():
pass
func.name = 'jason'
print(func.name)
BBS项目
1.项目开发流程
需求分析
架构师 开发组组长 草拟一些项目的大致技术点和流程
架构师 + 产品经理 + 开发组组长去客户公司听客户需求
在跟客户聊的时候 你要有意识有目的引导客户朝着你之前已经想好的
功能思路上去提需求
架构设计
架构师(框架 语言 数据库 缓存数据库 表设计 拆分功能 项目的报价(参与开发人员的个数 一个人1000~2000))
分组开发
开会(架构师组长会议) 分任务 按模块功能分的
开会(小组会议) 组长在拆分功能 每个组员写几个小功能
小组成员写代码
自己需要提前测试一下有没有bug
交付测试
妹纸多 见效最块的
一些不是显而易见的bug
如果是显而易见的bug 就需要扣你绩效
运维上线
1.委托给你们公司帮忙上线帮忙维护
2.交给对方公司
15K
基本工资 8000 6000
绩效 3000
岗位津贴 2000
其他补贴 2000
基本工资 12000
绩效 3000
2.表设计
先确定表名
再确定表字段
然后是表关系
用户表
- 利用auth_user表
- 手机号
- 头像
- 注册时间
- blog 一对一个人站点表
个人站点表
- 站点名称
- 站点标题
- 站点样式
文章标签表
- 标签名
- blog 一对多 个人站点表
文章分类表
- 分类名
- blog 一对多 个人站点表
文章表
-
文章标题
-
文章简介
-
文章内容
-
文章发布时间
-
blog 一对多个人站点表
-
tags 多对多文章标签表
-
category 一对多文章分类表
-
数据库优化设计方案
-
当有些数据需要要跨表查询得到时,可以直接定义成普通字段,通过代码同步更新,进行获取减少数据库压力. 文章的点赞数 点踩数 评论数 up_num down_num comment_num 在文章表中新添加三个普通字段跟对应的表中的数据同步更新即可
-
up_num 文章的点赞数
-
down_num 点踩数
-
comment_num 评论数
文章的点赞点踩表
- user_id 一对多用户表
- article_id 一对多文章表
- is_up booleanfield
文章的评论表
-
user_id 一对多用户表
-
article_id 一对多文章表
-
评论content TextField()
-
评论时间create_time
-
自关联
parent 跟自己所在的表外键关联
项目
mysql数据库的使用
创建数据库表
更改Settings中的数据库设置
__init__的设置
models表类的创建
使用django的自带表数据
from django.contrib.auth.models import AbstractBaseUser
多对多方式的建立,需要手动创建第三张表,并且外键字段through参数,在settings中配置指定使用自定义的数据表
新建static文件夹存放静态文件
settings设置 STATICFILES_DIRS
- settings
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bbs',
'USER': 'root',
'PASSWORD':'',
'HOST':'127.0.0.1',
'PORT': 3306,
'CHARSET': 'utf8'
}
}
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
# 设置指定使用django的默认表类
AUTH_USER_MODEL = 'app01.Userinfo'
- urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 注册功能
url(r'^register/',views.register)
]
- models
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
# 用户信息表
class Userinfo(AbstractUser):
phone = models.BigIntegerField(null=True)
# 该字段直接传文件即可,会自动将文件保存到avatar文件夹内,数据库里面存文件路径
# 如果没有传文件则会使用img文件夹下默认头像
avatar = models.FileField(upload_to='avatar/',default='static/img/default.jpg')
register_time = models.DateField(auto_now_add=True,null=True)
# 外键字段
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)
# 该字段存放的是用户自己写的css文件路径
site_theme = models.CharField(max_length=64)
# 分类表
class Category(models.Model):
name = models.CharField(max_length=32)
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)
# 数据库优化字段
up_num = models.IntegerField(default=0)
down_num = models.IntegerField(default=0)
comment_num = models.IntegerField(default=0)
# 外键字段
category = models.ForeignKey(to='Category',null=True)
blog = models.ForeignKey(to='Blog',null=True)
tags = models.ManyToManyField(to='Tag',through='Article2Tag',through_fields=('article','tags'))
# 文章和标签的第三张表
class Article2Tag(models.Model):
article = models.ForeignKey(to='Article')
tags = 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)
- myform
from django import forms
from app01 import models
class MyRegForm(forms.Form):
username = forms.CharField(max_length=8,min_length=3,label='用户名',
error_messages={
'max_length':'用户名最长8位',
'min_length':'用户名最短3位',
'required':'用户名不能为空'
},
widget=forms.widgets.TextInput(attrs={
'class':'form-control'
})
)
password = forms.CharField(max_length=8,min_length=3,label='密码',
error_messages={
'max_length':'密码最长8位',
'min_length':'密码最短3位',
'required':'密码不能为空'
},
widget=forms.widgets.PasswordInput(attrs={
'class':'form-control'
})
)
confirm_password = forms.CharField(max_length=8,min_length=3,label='确认密码',
error_messages={
'max_length':'确认密码最长8位',
'min_length':'确认密码最短3位',
'required':'确认密码不能为空'
},
widget=forms.widgets.PasswordInput(attrs={
'class':'form-control'
})
)
email = forms.EmailField(label='邮箱',error_messages={
'invalid':'邮箱格式不正确',
'required':'邮箱不能为空'
},widget=forms.widgets.EmailInput(attrs={'class':'form-control'})
)
# 局部钩子
# 校验用户名是否存在
def clean_username(self):
username = self.cleaned_data.get('username')
res = models.Userinfo.objects.filter(username=username)
if res:
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
from django.shortcuts import render,HttpResponseRedirect
from app01 import myform
from app01 import models
from django.http import JsonResponse
# Create your views here.
def register(request):
# 生成一个空的forms对象
form_obj = myform.MyRegForm()
if request.method == 'POST':
back_dic = {'code':1000,'msg':''}
# 对用户提交的数据先进行校验 forms
# 直接使用forms组件的校验方法,校验整个的数据字典
form_obj = myform.MyRegForm(request.POST)
if form_obj.is_valid():
# 如果数据校验结果正确
clean_data = form_obj.cleaned_data # 获取正确的数据 4个键值对
# 将确认密码的键值对弹出,只剩余三个便于创建用户
clean_data.pop('confirm_password')
# 获取用户上传的文件
file_obj = request.FILES.get('avatar')
# 判断文件是否存在,用户是否上传,如果没有上传才会设置default头像
if file_obj:
clean_data['avatar'] = file_obj # 四个键值对
# 自动创建,使用**直接打散关键字参数
models.Userinfo.objects.create_user(**clean_data)
# 添加成功界面信息,及跳转
back_dic['msg'] = '注册成功'
back_dic['url'] = '/login/'
else:
back_dic['code'] = 2000
# 将错误信息返回给前端
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>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">注册界面</h2>
{# input框的for循环显示#}
<form id="myform">
{% csrf_token %}
{% for foo in form_obj %}
<div class="form-group has-error">
{# label使得点击文本聚焦到input框中#}
<label for="{{ foo.auto_id }}">{{ foo.label }}</label>
{{ foo }}
<span class="error pull-right" style="color: red"></span>
</div>
{% endfor %}
{# 头像的标签框#}
<div class="form-group">
<label for="mdd">头像
<img src="/static/img/default.jpg" alt="" width="100px" style="margin-left: 10px" id="img">
</label>
{# 将input上传文件的框隐藏#}
<input type="file" name="avatar" id="mdd" style="display: none;">
</div>
{# 提交按钮#}
<input type="button" class="btn btn-success pull-right" value="注册" id="submit">
</form>
</div>
</div>
</div>
<script>
{#更换头像的图片域事件#}
$('#mdd').on('change',function () {
{#内置对象FileReader,完成文件的读取操作#}
let MyFileReader = new FileReader();
// 获取用户上传的文件对象
let fileObj = $(this)[0].files[0];
// 让文件阅读器读取文件
MyFileReader.readAsDataURL(fileObj); // 异步io操作
// 等待文件io操作读取完成再执行下面的代码
MyFileReader.onload = function () {
// 将读取之后的内容替换到img标签src属性中
$('#img').attr('src',MyFileReader.result)
}
});
{#提交按钮#}
$('#submit').click(function () {
// 将用户输入的数据全部发送给后端,普通的键值对和文件
let MyFormData = new FormData();
// FormData格式的数据传输,不停的添加键值对
{#MyFormData.append('','')#}
// 获取form表单里的所有input框的普通键值对serializeArray()
// 利用form标签内部有一个自动序列化普通键值对的方法 添加键值对
$.each($('#myform').serializeArray(),function (index,obj) {
MyFormData.append(obj.name,obj.value)
});
// 手动添加文件数据
MyFormData.append('avatar',$('#mdd')[0].files[0]);
// 发送ajax请求
$.ajax({
url:'',
type:'post',
data:MyFormData,
// 发送文件一定要指定两个参数
processData:false, //不要让浏览器处理你的数据
contentType:false, // 不要使用任何的编码,django能够识别对象自身
success:function (data) {
// 判断是否是正常的
if(data.code == 1000){
//跳转到登录页面
window.location.href = data.url
}else { // 如果保存,循环拼接,获取报错的input框下面的span
$.each(data.msg,function(index,obj){
{#index 就是报错字段,obj是报错信息 数组的形式#}
// 获取报错字典,手动拼接该字段所对应的input框的id值
let targetId = '#id_' + index;
$(targetId).next().text(obj[0].parent().addClass('has-error'))
})
}
}
})
});
{#input框获取焦点事件#}
$('input').focus(function () {
$(this).next().text('').parent().removeClass('has-error')
})
</script>
</body>
</html>