一、csrf跨站请求的相关装饰器
'''
django.middleware.csrf.CsrfViewMiddlewareDjango中有一个中间件对csrf跨站做了验证,我只要把csrf的这个中间件打开,
那就意味着所有的方法都要被验证
''' 在所有的视图函数中:只有几个视图函数做验证只有几个函数不做验证csrf_protect: 哪个视图函数加了这个装饰器,这个函数就会做验证
csrf_exempt:哪个视图函数加了这个装饰器,这个函数就不会做验证
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
注意:加入装饰器验证csrf,先导入下面这行代码:
from django. views. decorators. csrf import csrf_exempt, csrf_protect一、FBV模式下:
情境1 :1. 先在settings. py配置文件中注释下面这行代码:2. 然后在需要验证的视图函数上面加上 @csrf_protect 则说明这个视图函数需要经过验证. @csrf_protect def index ( request) : return render( request, 'index.html' ) def func ( request) : return render( request, 'func.html' ) 3. 上述两个视图函数中,由于index函数加了装饰器csrf_protect所以需要经过csrf验证,而func函数不需要情境2 :1. 先打开settings. py配置文件中下面这行代码:即不用注释'django.middleware.csrf.CsrfViewMiddleware' , 2. 然后在不需要验证的视图函数上面加上 @csrf_exempt 则说明这个视图函数不需要经过验证,而没有加任何装饰的视图函数必须经过csrf验证@csrf_exempt def index ( request) : return render( request, 'index.html' ) def func ( request) : return render( request, 'func.html' ) return render( request, 'func.html' ) 3. 上述两个视图函数中,在'django.middleware.csrf.CsrfViewMiddleware' , 没有被注释的情况下:由于index函数加了装饰器csrf_exempt,所以不需要经过csrf验证,而func函数需要csrf验证。情境3 :1. 在打开settings. py配置文件中下面这行代码的情况下:'django.middleware.csrf.CsrfViewMiddleware' , 2. 然后在不需要验证的视图函数上面加上 @csrf_exempt 则说明这个视图函数不需要经过验证,而另一个加了装饰器 csrf_protect 的视图函数也必须经过csrf验证@csrf_exempt def index ( request) : return render( request, 'index.html' ) @csrf_protect def func ( request) : return render( request, 'func.html' ) 3. 上述两个视图函数中,由于index函数加了装饰器csrf_exempt所以不需要经过csrf验证,而func函数加了装饰器csrf_protect需要csrf验证。二、CBV模式下:
注意:加入装饰器,先导入下面代码:
from django. views. decorators. csrf import csrf_exempt, csrf_protect
from django. views import View
from django. utils. decorators import method_decorator方式1 :在post函数上,加入csrf_exempt无效,还是报错:Forbidden ( 403 ) 1. 先打开settings. py配置文件中下面这行代码:即不用注释'django.middleware.csrf.CsrfViewMiddleware' , 2. 然后在不需要验证的视图函数上面加上 @csrf_exempt 则说明这个视图函数不需要经过验证,但是结果是还需要验证,说明此方式无效。class Login ( View) : @method_decorator ( csrf_exempt) def post ( self, request) : print ( 'post' ) return HttpResponse( 'post' ) 方式2 :在类的投诉,加入csrf_exempt无效,还是报错:Forbidden ( 403 ) 1. 先打开settings. py配置文件中下面这行代码:即不用注释'django.middleware.csrf.CsrfViewMiddleware' , 2. 在类的头上加了装饰器,但是还是无效@method_decorator ( csrf_exempt, name= 'post' ) class Login ( View) : def post ( self, request) : print ( 'post' ) return HttpResponse( 'post' ) 方式3 :CBV的验证只有在dispatch函数上加装饰器,需要验证的函数才能通过验证class Login ( View) : @method_decorator ( csrf_exempt) def dispatch ( self, request, * args, ** kwargs) : return super ( Login, self) . dispatch( request, * args, ** kwargs) def post ( self, request) : print ( 'post' ) return HttpResponse( 'post' ) 注意:在settings. py配置文件中注释下面这行代码:然后,对三种方式进行验证csrf_protect,都可以CBV针对于csrf_exempt:只有第三张方式才生效,其余两种方式不行
CBV针对于csrf_protect:三种方式都可以
class Login ( View) : @method_decorator ( csrf_protect) def dispatch ( self, request, * args, ** kwargs) : return super ( ) . dispatch( request, * args, ** kwargs) def post ( self, request) : print ( "post" ) return HttpResponse( "post" )
二、Auth模块的使用
Auth模块是什么?Auth模块是Django自带的用户认证模块:我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户数据。注意事项:在执行数据库迁移命令的时候,会自动生成一个默认的表,其中有auth_开头的很多表auth_user表的作用:djagno自带的后台管理系统所依赖的数据就在这张表中默认情况下,auth_user表是空表,没有用户名和密码,因此我们需要自己创建用户数据需要创建一个超级管理员账号才能登录'''
创建超级管理员命令:python manage.py createsuperuser在配置文件settings.py中修改语言为中文和时区:
# 语言
LANGUAGE_CODE = 'zh-hans'
# 时区
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False'''
三、Auth模块的相关方法
登录功能、注册功能、修改密码、退出系统、认证功能等学习如何使用
'''当局部和全局都存在的时候,按局部的如果局部没有,按照全局的
'''
@login_required ( login_url= '/order/login/' )
def order ( request) : pass LOGIN_URL = '/login/' '''
如果没有登录则 跳转到 http://127.0.0.1:8000/accounts/login/?next=/order/
但是若加了装饰器,则跳转到指定的路由页面在settings.py配置文件中全局配置,
LOGIN_URL = '/login/'当局部和全局都在的时候,按局部的,若局部没有,则按全局的
'''
@login_required ( login_url= '/login/' )
def order ( request) : print ( request. user. is_authenticated) return HttpResponse( 'order' ) def order1 ( request) : return HttpResponse( 'order' ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - auth模块的后端登录代码:
from django. contrib import authdef login ( request) : if request. method == 'POST' : username = request. POST. get( 'username' ) password = request. POST. get( 'password' ) '''这里的登录,我们使用auth模块,登录的时候所使用的表是auth_user表''' user_obj = auth. authenticate( request, username= username, password= password) '''返回值是登录成功之后的用户对象''' print ( user_obj) print ( user_obj. username) print ( user_obj. password) '''注意事项1:传递参数的时候,用户名和密码必须同时传入''' '''注意事项2:由于上面使用了auth模块,在此不建议这样写,auth模块都提供有相应的方法要么全部使用auth模块的方法,要么全部自己写,不建议混合使用''' auth. login( request, user_obj) '''只要写了auth.login,那么就可以在全局有任何request的地方使用request.user拿到用户对象''' return redirect( '/home/' ) return render( request, 'login.html' )
登录页面前端代码
<! DOCTYPE html >
< html lang = " en" > < head> < meta charset = " UTF-8" > < meta name = " viewport" content = " width=device-width, initial-scale=1.0" > < title> Document</ title> < style> body { { #background : url ( 'https://pic2.zhimg.com/3ae866e7992a94069c7e0c417aac807d_r.jpg' ) no-repeat; #} background : url ( 'https://img0.baidu.com/it/u=741268616,1401664941&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1691859600&t=5c5bee3052ecec363c1ecc2eea9ac3f7' ) no-repeat; background-size : 100% 130%; } #login_box { width : 20%; height : 400px; background-color : #00000060; margin : auto; margin-top : 10%; text-align : center; border-radius : 10px; padding : 50px 50px; } h2 { color : #ffffff90; margin-top : 5%; } #input-box { margin-top : 5%; } span { color : #fff; } input { border : 0; width : 60%; font-size : 15px; color : #fff; background : transparent; border-bottom : 2px solid #fff; padding : 5px 10px; outline : none; margin-top : 10px; } button { margin-top : 50px; width : 60%; height : 30px; border-radius : 10px; border : 0; color : #fff; text-align : center; line-height : 30px; font-size : 15px; background-image : linear-gradient ( to right, #30cfd0, #330867) ; } #sign_up { margin-top : 45%; margin-left : 60%; } a { color : #b94648; } </ style>
</ head> < body>
< div id = " login_box" > < h2> 登录页面</ h2> < form action = " " method = " post" > < div id = " input_box" > < input type = " text" placeholder = " 请输入用户名" name = " username" > </ div> < div class = " input_box" > < input type = " password" placeholder = " 请输入密码" name = " password" > </ div> < button> 提交</ button>
{# < input type = " submit" value = " 提交" > #}< br> </ form>
</ div>
</ body>
</ html>
四、Auth模块之退出系统
def logout ( request) : auth. logout( request) return redirect( '/home/' )
六、Auth模块之修改密码功能
1. 验证老密码是否正确
is_right = request. user. check_password( old_password) 2. 修改密码
request. user. set_password( new_password)
request. user. save( ) 案例代码:
@login_required
def set_password ( request) : if request. method == 'POST' : old_password = request. POST. get( 'old_password' ) new_password = request. POST. get( 'new_password' ) re_password = request. POST. get( 're_password' ) if new_password == re_password: is_right = request. user. check_password( old_password) if is_right: request. user. set_password( new_password) request. user. save( ) return redirect( '/home/' ) return render( request, 'set_password.html' , locals ( ) ) 前端代码:
< div id = "login_box" > < h2> 修改密码< / h2> < form action= "" method= "post" > { % csrf_token % } < div id = "input_box" > 用户名:< input type = "text" name= "username" readonly value= "{{ request.user.username }}" > < / div> < div class = "input_box" > 旧密码:< input type = "password" placeholder= "请输入旧密码" name= "old_password" > < / div> < div class = "input_box" > 新密码:< input type = "password" placeholder= "请输入新密码" name= "new_password" > < / div> < div class = "input_box" > 请确认:< input type = "password" placeholder= "确认新密码" name= "re_password" > < / div> < button> 提交< / button>
{ < br> < / form>
< / div>
七、Auth模块之注册功能
'''
入库的三种方式:方式1:自动入库到auth_user表,但是密码是明文密码,登录的时候是经过加密处理的,则登录不上User.objects.create(username=username, password=password)方式2:密码是密文入库User.objects.create_user(username=username, password=password)方式3:创建超级用户,并且密码是密文存入,但是必须指定邮箱,否则报错User.objects.create_superuser(username=username, password=password, email='123@qq.com')
''' from django. contrib. auth. models import Userdef register ( request) : if request. method == 'POST' : username = request. POST. get( 'username' ) password = request. POST. get( 'password' ) User. objects. create_superuser( username= username, password= password, email= '123@qq.com' ) return redirect( '/login/' ) return render( request, 'register.html' )
八、扩展默认的auth_user表
默认情况下使用的就是auth_user的默认字段
扩展我们自己的字段前提是:所有的模型类都继承
from django. contrib. auth. models import AbstractUser现在是要在auth_user表的基础上扩展字段,不要继承了models. Model** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
注意:扩展之后需要在配置文件( settings. py) 中加一句话AUTH_USER_MODEL = '应用名.表名' eg: AUTH_USER_MODEL = 'app01.UserInfo' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 注意:"""在扩展表之前数据库不能够迁移,扩展这个表需要在迁移数据库之前做""" 问:如果你迁移了,还想扩展怎么办?1. 换库2. 需要删除很多个应用的migrations文件夹
注意:迁移报错的时候,有可能会用到下面这句代码:python manage. py migrate myapp - - fake- - - - - - - - - - - - - - - 重点:扩展表之后发生的变化- - - - - - - - - - - - - - - - - - -
"""扩展表之后发生的变化:1. 原来的auth_user表不存在了,换成你自己新建的表名了2. 原来的auth_user表中的字段还都在,然后多了自己扩展的字段3. 继承的类要发生改变AbstractUser4. 在配置文件中加入下面一句话:AUTH_USER_MODEL = 'app01.UserInfo'AUTH_USER_MODEL = '应用名.类名'5. 扩展之后还是按照原来的auth_user表使用6. auth模块中的数据还是你扩展的表7. 扩展之前别迁移.
""" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
案例:
因为之前迁移过了,所以我选择换库:从sqlite3- - - - > mysql1. 在settings. py配置文件中把数据库换成MySQL:
'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' : 'db22' , 'HOST' : '127.0.0.1' , 'PORT' : 3306 , 'USER' : 'root' , 'PASSWORD' : 'root' , 'CHARSET' : 'utf8' } ,
2. 扩展表的字段:先导入AbstractUser,让扩展表继承AbstractUser
from django. contrib. auth. models import AbstractUser
class UserInfo ( AbstractUser) : phone = models. CharField( max_length= 64 ) avatar = models. CharField( max_length= 64 )
3. 迁移
python manage. py makemigrations
python manage. py migrate