day61(* csrf相关装饰器 * 基于中间件思想编写项目 auth认证模块 )
今日内容概要
-
csrf相关装饰器
-
基于中间件思想编写项目
将功能封装成配置的形式 实现可插拔式设计 # 非常重要
-
auth认证模块
-
bbs项目分析
-
bbs项目表设计
今日内容详细
csrf相关装饰器
如果你不想让某个方法csrf校验就直接给这个方法装上@csrf_exempt这个装饰器
第一步导入模块
from django.views.decorators.csrf import csrf_exempt,csrf_protect
"""
csrf_exempt
忽略csrf校验
"""
"""如果你不想让某个方法csrf校验直接为这个方法装上装饰器"""
针对FBV
@csrf_exempt
def login(request):
return render(request, 'login.html')
同理你想让那个方法开启csrf校验就给他装上@csrf_protect
csrf_protect
开启csrf校验
"""如果你是全局csrf校验被你注释掉之后你想单独开启某一个csrf校验你就给他加上@csrf_protect"""
@csrf_protect
def index1(request):
return render(request, 'index1.html')
针对CBV开启csrf校验三种方法都可以 @method_decorator(csrf_protect)
from django import views
from django.utils.decorators import method_decorator
"""第二种方式直接给类装用name指定是那个方法例如name='post'
@method_decorator(csrf_protect, name='post')
"""
@method_decorator(csrf_protect, name='post')
class MyViews(views.View):
"""第三种自定义一个dispatch方法"""
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
super(MyViews,self).dispatch(request,*args,**kwargs)
"""第一种方式直接在类里面的函数方法装上装饰器@method_decorator(csrf_protect)"""
# @method_decorator(csrf_protect)
def post(self, request):
return HttpResponse('from MyView post')
针对CBV csrf_exempt忽略csrf校验
只有 只有一种方式可以生效(给重写的dispatch方法装)
代码:
class MyViews(views.View):
"""第三种自定义一个dispatch方法只有第三种可以"""
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(MyViews,self).dispatch(request,*args,**kwargs)
def post(self, request):
return HttpResponse('from MyView post')
回顾复习CBV和FBV概念:
回顾复习CBV和FBV概念:
FBV
FBV(function base views) 就是在视图里使用函数处理请求。
CBV
CBV(class base views) 就是在视图里使用类处理请求。
CBV 模式优势总结了如下几点:
CBV 将整个视图函数的逻辑拆成了类下的多个函数,依靠函数调用来实现完整的逻辑;
提高代码的可复用性,更加灵活,让开发者使用面向对象的技术,比如多继承、多态等;
可以用不同的函数针对不同的 HTTP 方法处理,而不是通过很多 if 判断,提高代码可读性。
当然 CBV 也不是万能的,当继承关系变得很复杂,亦或是代码不是特别规整的时候,这时要去找某一个函数到底是被哪一个父类重载也是一个麻烦事。此时使用 FBV 模式就变的很方便,所以还是要理解它们两者的区别,在合适的场景选用合适的方法,不能把其中某一种模式视为唯一。总体上来说 CBV 的模式,在实际的开发工作中使用的相对较多,所以我们要掌握这种编写 view 视图函数的模式。
FBV(基于函数的视图)
FBV(function based views),即基于函数的视图;CBV(class based views);也是基于对象的视图。说白了就是在每一个views中添加自己专用的方法。FBV 简单易懂,但是难以复用。它们不能像 CBV 那样能从父类中继承。FBV 的编写指南要求我们:视图代码越少越好;视图代码不能重复;视图应该只处理呈现逻辑。业务逻辑应尽可能放在数据模型中,或者表单对象中;视图代码要保持简单;使用它们来编写自定义的 403, 404, 500 等错误处理器;避免使用嵌套的 if 块。CBV是View类的集成类;这里的主要区别在于请求是以HTTP方法命名的类方法内处理的,例如GET ,POST ,PUT ,HEAD等。所以,在这里,我们不需要做一个条件来判断请求是一个 POST 还是它是一个 GET 。代码会直接跳转到正确的方法中,在 View 类中内部处理了这个逻辑。
基于中间件思想编写项目
importlib模块
首先第一个知识点就是补充# importlib模块可以通过字符串的形式导入模块
我们可以看到settins文件中有这么一些东西,七个中间件其实我们仔细把他拆分开看一下就变成了这样
from django.middleware.security import SecurityMiddleware
也就意味着他是通过字符串的形式导入模块所以我们接下来要学习 importlib模块
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
#importlib模块他的最小层级单位只能是py文件级别不能是变量级别
a.py:
# 普通导入
from ccc import b
print(b.name)
print(b)
# 字符串导入方式
import importlib
"""注意首先这个字符串不是乱写的一个字符串他是一个路径所对应的字符串"""
module_path = 'ccc.b'
res=importlib.import_module(module_path)
"""res 相当是模块b,具备其所有它的功能"""
print(res)
print(res.name)
print(res.__name__)
ccc文件下b.py:
name='from ccc.b zqh'
以发送提示信息为需求 编写功能
方式1:封装成函数
方式2:封装成配置
import settings
import importlib
def send_all(msg):
# 1.循环获取配置文件中字符串信息
for str_path in settings.NOTIFY_FUNC_LIST: # 'notify.email.Email'
# 2.切割路径信息,切割完成之后 moudle_path相当于=='notify.email',而class_str_name=='Email'也就是类名
module_path, class_str_name = str_path.rsplit('.', maxsplit=1) # ['notify.email','Email']
# 3.根据module_path导入模块文件
module = importlib.import_module(module_path) from notify import email
# 4.利用反射获取模块文件中对应的类名
class_name = getattr(module, class_str_name) # Email Msg QQ
# 5.实例化
obj = class_name()
# 6.调用发送消息的功能
obj.send(msg) [Microsoft Edge.lnk](C:\Users\Public\Desktop\Microsoft Edge.lnk)
回顾学习
首先回顾一下rspilt从右切割字符串
回顾getattr反射:
getattr(object,name [,默认])
返回对象的命名属性的值。 名称必须是字符串。 如果字符串是对象属性之一的名称,则结果是该属性的值。 例如,getattr(x,‘foobar’)等效于x.foobar。 如果指定的属性不存在,则返回默认值(如果提供),否则引发AttributeError。
函数功能是从对象object中获取名称为name的属性,等效与调用object.name。
# 定义类Student
class Student:
def __init__(self, name):
self.name = name
s =Student('Aim')
ad=getattr(s, 'name') # 等效于调用s.name
print(ad)
print(s.name)
函数第三个参数default为可选参数,如果object中含义name属性,则返回name属性的值,如果没有name属性,则返回default值,如果default未传入值,则报错。
#定义类Student
class Student:
def __init__(self,name):
self.name = name
getattr(s,'name') #存在属性name
'Aim'
getattr(s,'age',6) #不存在属性age,但提供了默认值,返回默认值
6
getattr(s,'age') #不存在属性age,未提供默认值,调用报错
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
getattr(s,'age')
AttributeError: 'Stduent' object has no attribute 'age'
auth认证模块
# django提供给你快速完成用户相关功能的模块
用户相关功能:创建、认证、编辑...
# django也配套提供了一张'用户表'suth_user用户认证表
执行数据库迁移命令之后默认产生的auth_user
# django自带的admin后台管理用户登录参考的就是auth_user表
创建admin后台管理员用户:run manage.py task>>:createsuperuser
自动对用户密码进行加密处理并保存
auth模块方法大全
""" auth模块方法大全"""
from django.contrib import auth
"""登录保存"""
def lg(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
"""判断几个就传入几个 下面这句话是直接给你做加密处理然后进行比对"""
is_user_obj = auth.authenticate(request, username=username, password=password)
"""auth.login保存用户登陆状态"""
if is_user_obj:
auth.login(request, is_user_obj)#自动操作session相关
return HttpResponse('牛马置密码完成')
return render(request, 'lg.html')
"""获取当前登录用户 如果没登陆获取匿名用户 {AnonymousUser}"""
def get_user(request):
# print(request.user)
"""request.user.is_authenticated() 判断用户是否登录 返回布尔值"""
# print(request.user.is_authenticated())
if request.user.is_authenticated():
print(request.user.username)
print(request.user.password)
print(request.user.email_user)
print(request.user.last_login)
"""
zhao
pbkdf2_sha256$36000$7q2cKzOX7i1y$PAWMZrBW8TjoB8RPKydWfRHGFm4bs3ixyGhmtS3NS5M=
<bound method AbstractUser.email_user of <User: zhao>>
2022-05-25 10:58:41.438052+00:00
"""
return HttpResponse('查看牛马是否已存在')
"""局部配置 装饰器 加上装饰器之后@login_required() 用户如果你没有跳转会默认跳转到/accounts/login/?next=/home/ 可以自定义
自定义方法就是@login_required(login_url='/lg/')在括号中定义跳转页面"""
from django.contrib.auth.decorators import login_required
@login_required(login_url='/lg/')
def index(request):
return HttpResponse('index页面只有登录牛马可以查看')
@login_required()
def home(request):
return HttpResponse('home页面只有登录牛马可以查看')
@login_required()
def func(request):
return HttpResponse('func页面只有登录牛马可以查看')
"""修改密码"""
@login_required
def set_password(request):
if request.method=='POST':
old_password= request.POST.get('old_password')
new_password= request.POST.get('new_password')
"""check_password 等于是临时拿到密码并且把密码加密比对"""
is_right= request.user.check_password(old_password)
if is_right:
"""set_password 就是对比成功之后设置新的密码"""
request.user.set_password(new_password)
"""save 设置成功进行保存保存到数据库中"""
request.user.save()
return render(request,'set_password.html',locals())
#set_password.html代码:
<body>
{%csrf_token%}
<form action="" method="post">
<p>username
<input type="text" value="{{ request.user.username }}" disabled>
</p>
<p>old_password:
<input type="text" name="old_password">
</p>
<p>new_password:
<input type="text" name="new_password">
</p>
<input type="submit">
</form>
</body>
"""清空账户"""
@login_required
def logout(request):
auth.logout(request)
return HttpResponse('注销')
"""注册功能"""
def register(request):
User.objects.create_superuser(username='lcxNB', password='lcxNB', email='123@qq.com') 创建超级用户管理员
User.objects.create_user(username='jason',password='jason123') 创建普通用户
return HttpResponse('牛马注册成功')
注意如果是想使用全局配置固定跳转
在settings中配置一下代码如下
LOGIN_URL='/lg/'
auth扩展表字段
首先如果你想进行类继承就直接开设一个新的数据库因为这样很直接也能少很多麻烦、
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
"""使用这个方法导入模块继承 AbstractUser 拥有他里边的所有字段所有功能"""
class MyUser(AbstractUser):
"""然后编写进行编写 注意:编写这个表里边没有的字段,不能冲突"""
phone = models.BinaryField()
addr = models.CharField(max_length=32)
# 方式1:编写一对一表关系(了解)
# 方式2:类继承(推荐)
from django.contrib.auth.models import AbstractUser
class Users(AbstractUser):
# 编写AbstractUser类中没有的字段 不能冲突!!!
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)
AUTH_USER_MODEL = 'app01.Users'
"""
1.类继承之后 需要重新执行数据库迁移命令 并且库里面是第一次操作才可以
2.auth模块所有的方法都可以直接在自定义模型类上面使用
自动切换参照表
"""
ps:课下可以先继承表 之后才练习auth所有的方法
项目开发流程
1.需求分析
2.技术选型
3.分组开发
4.提交测试
5.交付上线
"""
我们以后写项目 一般都是从数据库设计开始!!!
一个好的数据库设计 会让我们写代码变得非常的轻松
"""
bbs数据表分析
"""
1.先确定表
2.再确定字段
3.最后确定关系
"""
1.用户表
继承AbstractUser
2.个人站点表
站点名称、标题、样式
3.文章表
标题、简介、内容、发布时间
4.文章分类表
分类名称
5.文章标签表
标签名称
6.文章点赞点踩表
文章、用户、赞/踩
7.文章评论表
文章、用户、评论内容、评论时间
ps:提前思考表关系
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下