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>
1206 BBS注册的更多相关文章
- BBS注册功能
BBS注册功能 一.后端 1.组件校验数据 """ @author RansySun @create 2019-11-03-11:35 """ ...
- discuz bbs注册,登录流程整理!想打通bbs又不想读一遍代码可以参考一下
bbs 用户注册流程 第一步: /source/class/class_member.php: on_register注册入口 L602 左右 if(!$activation) {//不为空,说明用户 ...
- 史上最全的FTP网址
无帐号密码的为匿名登录 ftp://202.114.1.121 ftp://202.114.10.199 ftp://warez:cn.ftp@202.114.12.174 ftp://Music2: ...
- BBS(第一天)项目之 注册功能实现通过forms验证与 前端ajax请求触发查询数据库判断用户是否存在的功能实现
1.BBS项目之注册功能通过forms验证 from django import forms from blog.models import User from django.contrib.auth ...
- BBS - 表、登录、文件上传、注册
一.博客系统得表关系 models.py from django.db import models from django.contrib.auth.models import AbstractUse ...
- BBS论坛 注册功能
三.注册功能 # views.py文件 def register(request): back_dic = {'code': 100, 'msg': ''} form_obj = myforms.My ...
- 扩展auth_user字段、BBS需求分析、创建BBS数据库、注册页面搭建与用户头像展示及Ajax提交数据
昨日内容回顾 csrf跨站请求 1. SQL注入 2. xss攻击 3. csrf跨站请求 4. 密码加密(加盐) '''django中默认有一个中间件来验证csrf''' # 只针对post请求才验 ...
- BBS登录与注册功能
登录功能 视图函数 def my_login(request): if request.method == 'GET': return render(request, 'login.html') el ...
- bbs论坛注册功能(1)
分析项目需求创建表: STATICFILE_DIR = [ os.path.join(BASE_DIR,'static') #设置目录,bootstrip添加到目录中去,直接本地调用 ] # auth ...
随机推荐
- 博客迁移到github了
博客迁移到github了,这边基本不更新, 主要是没有找到快捷的同步方法,手动同步太麻烦了,如果你有快速把github博客同步到博客园的方法请一定告诉我
- Linux中DHCP服务器的简单配置(转)
我安装了两台linux系统,一个作为服务器,一个客户端 两个都有3个网卡, 后两个网卡聚合为zhi一个网卡:Linux 网卡聚合 两台电脑都一样. 那么如何为这个聚合网卡进行DHCP的分配呢? 1.由 ...
- Qt5 QtQuick系列----QtQuick的Secne Graph剖析(1)
教是言词, 实不是道,道本无言, 言说是妄.------- 达摩 Qt 5提出了一个新的渲染底层,以替代Qt4时期的Graphics View,这个渲染底层就是Scene Graph.Scene Gr ...
- QT虚拟小键盘设计--qt事件循环,事件发送的理解
有人讲到QT5.7及其以后的版本才自带免费的小键盘插件. QT5.10中关于QKeyEvent类:点击打开链接 QT sendEvent和PostEvent, 点击打开链接 my god,我今天安装了 ...
- python类型检测最终指南--Typing模块的使用
正文共:30429 字 预计阅读时间:76分钟 原文链接:https://realpython.com/python-type-checking/ 作者:Geir Arne Hjelle 译者:陈祥安 ...
- Pytorch1.3源码解析-第一篇
pytorch$ tree -L 1 . ├── android ├── aten ├── benchmarks ├── binaries ├── c10 ├── caffe2 ├── CITATIO ...
- Integer的parseInt和valueOf的区别
先来看一下下面这段代码 String s = "1"; System.out.println(Integer.valueOf(s)); System.out.println(Int ...
- 装饰器login_required
装饰器login_required将游客身份引导至登录页面,登录成功后跳转到目的页面 url.py path('login/',views.login), path('home/',views.hom ...
- Go语言( 函数)
函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数 Go语言中支持函数.匿名函数和闭包,并且函数在Go语言中属于“一等公民”. 函数定义 Go语言中定义 ...
- [UOJ #167]【UR #11】元旦老人与汉诺塔
题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...