<form action="" method="post">
<p>用户:<input type="text" name="username">p> 转账人
<p>目标用户:<input type="text" name="target_name">p> 收款人
<p>转账金额:<input type="text" name="money">p> 转账金额
<input type="submit">
form>
<form action="http://127.0.0.1:8000/login/" method="post"> 直接给真网站发送请求
<p>用户:<input type="text" name="username">p>
<p>目标用户:<input type="text">p> 不设置name属性,使这一标签没有实际作用
<input type="text" name="target_name" value="xxx" style="display: none"> 自己设定收款人,并将标签隐藏
<p>转账金额:<input type="text" name="money">p>
<input type="submit">
form>
之前一直注释掉的中间件,就是用来发送标识信息的
将其注释了代表任意页面都能够直接发送post请求
启用后再发送post请求需要添加模板语法
1. form表单
<form action="" method="post">
{% csrf_token %}
form>
2. ajax
方式1:先编写csrf模板语法,然后利用标签查找和值获取,手动添加
{% csrf_token %}
<button id="d1">btnbutton>
<script>
$('#d1').click(function(){
$.ajax({
url: '',
type: 'post',
data: {"csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val()},
success: function(){
}
})
})
方式2:利用模板语法
data: {"csrfmiddlewaretoken": "{{ csrf_token }}"}
方式3:通用方式(js脚本)
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
将以上代码放入js文件中,需要使用在html中导入文件即可
当整个网站默认都不校验csrf或者全部校验csrf,可以单独设置指定函数需不需要校验
FBV:
from django.views.decorators.csrf import csrf_protect,csrf_exempt
"""
csrf_protect:校验csrf
csrf_exempt:不校验csrf
直接在指定的视图函数上装饰即可
"""
@csrf_protect
def func1(request):
return HttpResponse('func1')
@csrf_exempt
def func2(request):
return HttpResponse('func2')
CBV:
"""CBV针对于装饰器不能够直接添加,需要使用专门添加装饰器的方法"""
from django import views
from django.utils.decorators import method_decorator # 使用该模块添加装饰器
from django.views.decorators.csrf import csrf_protect, csrf_exempt
@method_decorator(csrf_protect, name='post') # 方式2:装饰给类,指定装饰的方法名
class Index(views.View):
@method_decorator(csrf_protect) # 方式3:装饰所有方法
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request):
return render(request, 'login.html')
@method_decorator(csrf_protect) # 方式1:直接在指定方法添加装饰器
def post(self, request):
return HttpResponse('post')
"""针对于csrf_exempt只有方式3有效"""
django执行数据库迁移命令后会产生一张auth_user表
该表可以配合auth模块做用户相关的功能:登录、注册、修改密码等
该表还是django admin后台管理默认使用的表
命令行创建django admin后台管理员:python manage.py createsuperuser
from django.contrib.auth.models import User # 创建用户需要先导入该表
User.objects.create()
User.objects.create_user(username=username,password=password)
User.objects.create_superuser(username=username,password=password,email=email) # 管理员用户需要填写邮箱
"""有三种创建方式
第一个不建议使用,密码不会自动加密
第二个为创建普通用户
第三个为创建管理员用户
"""
from django.contrib import auth
user_obj = auth.authenticate(request,username,password) # 如果用户名与密码能够匹配上,返回用户对象;否则返回None
from django.contrib import auth
auth.login(request,user_obj) # 提供一个通过校验的用户对象,会在后端为该用户生成相关的session数据
res = request.user.is_authenticated
"""当前登录了返回True,否则返回False"""
user_obj = request.user
"""
如果当前登录了返回当前登录用户对象
如果没有登录则返回一个匿名用户
"""
print(user_obj.username) # 如果是匿名用户返回空
print(user_obj.password) # 匿名用户点password会报错
from django.contrib.auth.decorators import login_required
@login_required()
def func(request):
return HttpResponse('func')
"""
如果当前用户没有登录,跳转到默认登录页面:/accounts/login/
也可以设置跳转的登录页面:login_required(login_url='/login/')
如果想要全局都使用一个登录页面,则可以在配置文件中添加配置:LOGIN_URL='/login/'
"""
request.user.check_password('password')
"""会自动加密括号内密码判断是否与当前登录账号密码一致;返回布尔值"""
request.user.set_password('new_password')
request.user.save()
"""
将密码修改为括号内的新密码
需要注意修改完后必须保存,否则修改不生效
"""
from django.contrib import auth
def logout_fn(request):
auth.logout(request)
return HttpResponse('logout')
"""调用该函数时,会将当前请求的session信息全部清除"""
当内置的表字段不够用,想要添加更多字段,那么就可以通过继承内置的AbstractUser类,来定义一个自己的Model类
models.py:
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
"""继承后直接扩展auth_user表中没有的字段即可"""
phone = models.BigIntegerField()
在自定义了auth_user表后,需要在setting中配置好,当前应该使用我们自定义的表来做用户认证
setting:
AUTH_USER_MODEL = 'app01.Userinfo' # 应用名加类名
"""python导入模块的第三种方式:通过字符串导入"""
import importlib
s1 = 'app01.aaa.func'
res = importlib.import_module(s1)
"""
res就相当于是func.py对象,可以直接点出其中方法
需要注意此方法最多只能到py文件,不能够在细化
原理相当于是切割字符串,然后导入:s1.rsplit('.',maxsplit=1)
"""
"""在里边存放想要执行的类"""
NOTIFY_FUNC_LIST = [
'notify.qq.QQ',
'notify.weixin.WeiXin',
'notify.msg.Msg',
]
然后在notify包中创建各个类
class QQ(object):
def __init__(self):
pass # 模拟发送qq之前 应该准备的代码环境
def send(self, content):
print('qq消息通知:', content)
创建启动文件
import notify # 导入包会导入包的__init__文件
if __name__ == '__main__':
notify.send_all('messages')
在__init__文件中执行各个模块的方法
import importlib
import settings
def send_all(content):
for i in settings.NOTIFY_FUNC_LIST: # 'day64.notify.qq.QQ',循环获取每个字符串
module_path, class_str_name = i.rsplit('.', maxsplit=1) # 'day64.notify.qq' 'QQ',将字符串分为文件路径与类名
module = importlib.import_module(module_path) # 获取py文件对象
class_name = getattr(module, class_str_name) # 通过文件对象与文件对象中的方法(类名)字符串,使用反射获取真正的类名
obj = class_name() # 实例化一个对象
obj.send(content) # 由于是鸭子类型,所有类都是同一个方法