Form组件
【一】Django中的form组件
1)功能
- 可以帮我们渲染页面、校验数据、展示提示信息
2)使用案例
- 在App中创建一个py文件
# 引入
from django import forms
# 创建一个form组件类
class LoginForm(forms.Form):
username = forms.CharField(
max_length=8,
min_length=3,
label='用户名'
)
password = forms.CharField(
min_length=3,
label='密 码'
)
- 引入使用创建组件
# views
# 导入自定义的组件类
from ... import LoginForm
def login(request):
# 实例化组件类得到组件
login_form = LoginForm()
# 渲染标签
if request.method == "POST":
# form组件帮我们校验数据
data = request.POST
print(data)
# < QueryDict: {'username': ['12345'], 'password': ['123']} >
form_obj = LoginForm(data=data)
print(form_obj.is_valid())
# 符合:True、不符合:False
return render(request, 'login.html', locals())
- 前端写入
- form.errors 提取当前form组件验证当前字段数据对应的错误信息
<h1>form表单登陆页面</h1>
<form action="" method="post">
{{ login_form }}
{{login_form.errors}}
<p><input type="submit"></p>
</form>
3)校验数据
1.数据是否合法(is_valid)
- 每个Django表单的实例都有一个内置的is_valid()方法,用来验证接收的数据是否合法
form_obj.is_valid()
# 合法:True、不合法:False
2.查看合法的数据(cleaned_data)
-
如果所有数据都合法,那么该方法将返回True,并将所有的表单数据转存到它的一个叫做cleaned_data的属性中,该属性是一个字典类型数据
form_obj.cleaned_data # data = {'username': 'ST1', 'password': '123'}
3.查看合法数据(changed_data)
-
查看当前哪些字段数据进行过校验
form_obj.changed_data # ['username', 'password']
4.查看错误的数据(errors)
-
查看所有不符合规则的参数及不符合的原因
-
报错原因可能有多个
form_obj.errors
5.小结
- 默认情况下
- 多传不校验
- 少传会报错
【二】常用字段及插入
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 添加初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
...
BooleanField(Field)
...
NullBooleanField(BooleanField)
...
ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, 查询数据库中的数据
empty_label="---------", 默认空显示内容
to_field_name=None, HTML中value的值对应的字段
limit_choices_to=None ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
...
UUIDField(CharField) uuid类型
【三】渲染HTML代码
1)直接渲染
<form action="" method="post">
{{ form_obj }}
<p><input type="submit"></p>
</form>
2)渲染成列表元素
<form action="" method="post">
{{ form_obj.as_ul }}
<p><input type="submit"></p>
</form>
3)渲染成p标签
<form action="" method="post">
{{ form_obj.as_p }}
<p><input type="submit"></p>
</form>
4)渲染成表格元素
<form action="" method="post">
<table>
{{ form_obj.as_table }}
</table>
<p><input type="submit"></p>
</form>
5)for遍历渲染
<form action="" method="post">
{% for form in form_obj %}
<p> {{ form.label }} : {{ form }}</p>
{% endfor %}
<p><input type="submit"></p>
</form>
【四】渲染错误信息
- 使用
{{form.errors}}
模板语法,在表单里处理错误信息 - 对于每一个表单字段的错误,其会生成一个无序列表
1)遍历渲染错误信息
<form action="" method="post">
{% for field in login_form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<p><input type="submit"></p>
</form>
- field常用属性
属性 | 说明 |
---|---|
{{ field.label }} | 字段对应的label信息 |
{{ field.label_tag }} | 自动生成字段的label标签,注意与{{ field.label }}的区别。 |
{{ field.id_for_label }} | 自定义字段标签的id |
{{ field.value }} | 当前字段的值,比如一个Email字段的值[email protected] |
{{ field.html_name }} | 指定字段生成的input标签中name属性的值 |
{{ field.help_text }} | 字段的帮助信息 |
{{ field.errors }} | 包含错误信息的元素 |
{{ field.is_hidden }} | 用于判断当前字段是否为隐藏的字段,如果是,返回True |
{{ field.field }} | 返回字段的参数列表。例如{{ char_field.field.max_length }} |
2)禁止浏览器做校验
- 浏览器自动帮我们做数据校验,但也可以取消
<form action="" method="post" novalidate>
{% for form in login_form %}
<p> {{ form.label }} : {{ form }}</p>
<span style="color: red">{{ login_form.errors }}</span>
{% endfor %}
<p><input type="submit"></p>
</form>
【五】钩子函数
- 用来在特定事件发送时执行自定义逻辑的函数
1)常见的钩子函数
-
onInputChange
- 当输入框的值发生变化时触发。
- 你可以通过这个钩子函数获取最新的输入值,并进行相应的处理。
-
onSubmit
- 当表单提交时触发。你可以在这个钩子函数中获取表单中的所有字段值,并进行数据验证、提交或其他操作。
-
onBlur
- 当输入框失去焦点时触发
- 你可以在这个钩子函数中执行验证操作
- 例如检查输入是否符合预期的格式或是否满足某些条件。
-
onFocus
- 当输入框获得焦点时触发。
- 你可以在这个钩子函数中执行一些针对输入框焦点状态的逻辑操作
- 例如显示一个下拉列表或提示信息。
-
onReset
- 当表单重置时触发
- 你可以在这个钩子函数中对表单进行一些初始化操作
- 将表单恢复到初始状态。
-
局部钩子
- 当需要给某个字段增加校验规则的时候使用
- 在自定义的 forms 类中添加类方法即可
-
全局钩子
- 当需要给多个字段增加校验规则的时候使用
- 在自定义的 forms 类中添加类方法即可
2)钩子的使用样式
# 创建的py文件
class LoginForm(forms.Form):
username = forms.CharField(
max_length=8,
min_length=3,
label='用户名'
)
password = forms.CharField(
min_length=3,
label='密 码'
)
# 当输入的内容符合条件 进入钩子函数
# 局部钩子
def clean_password(self):
# 取出参数
password = self.cleaned_data.get('password')
print(password)
# 进行校验(是否以!开头)
if password.startswith('9'):
# 方案一:抛出异常
raise forms.ValidationError('密码不能以9开头')
if password.startswith('0'):
# 方案二:给字段添加错误信息
self.add_error('password', '密码不能以0开头')
# 放回参数
return password
# 全局钩子
def clean(self):
# 取出参数
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username == password:
self.add_error('username', '与密码重复')
self.add_error('password', '与用户名重复')
# 放回参数
return self.cleaned_data
# views
from App.form_eg import LoginForm
def login_2(request):
login_form = LoginForm()
if request.method == "POST":
login_form = LoginForm(request.POST)
if not login_form.is_valid():
print(login_form.errors)
return render(request, 'login_2.html', locals())
# 前端
<form action="" method="post">
{{ login_form }}
<p><input type="submit"></p>
</form>
【六】Cookie和Session
1)引入
- Cookie和Session是Web应用程序中常用的用户会话跟踪技术。
- Cookie通过在客户端存储小型文本文件,并将会话标识符传递给服务器,实现会话状态的保持。
- 而Session则是在服务器端存储会话数据,通过Session ID实现对用户会话的追踪。
2)介绍
- cookie是保存在客户端浏览器上的信息
- session是保存在服务端上的信息
- session是基于cookie工作的(其实大部分的保存用户状态的操作都需要使用cookie)
3)Django操作Cookie
1.示例演示
- cookie主页
def home_c(request):
# 实例化、渲染form组件
login_form = loginForm()
if request.method == 'POST':
data = request.POST
username = data['username']
password = data['password']
# 模拟登录校验
if username == 'ST1' and password == '123':
# 创建三板斧对象
obj = redirect(reverse('home_c'))
# 设置cookie信息
obj.set_cookie('login', 'login_true')
return obj
else:
return redirect(reverse('homepage'))
return render(request, 'cookie/home_c.html', locals())
- 登录后才能查看的页面
def login(request):
# 获取登录设置的cookie
cookie = request.COOKIES.get('login')
# 校验信息
if cookie == 'login_true':
return render(request, 'cookie/login.html', locals())
else:
return redirect(reverse('home_c'))
- 退出登录
def logout(request):
# 指定要清除的cookie页面
obj = redirect(reverse('home_c'))
# 删除cookie
obj.delete_cookie('login')
return obj
2.小结
-
设置cookie
# 创建三板斧对象 # (render, HttpResponse,redirect, reverse) obj = redirect(reverse()) # 设置cookie信息 obj.set_cookie('key', 'value') return obj
-
获取cookie
cookie = request.COOKIES.get('key')
-
注销cookie
# 指定要清除的页面 obj = redirect(reverse()) # 删除cookie obj.delete_cookie('key')
-
设置超时时间
- max_age :设置超时时间,以秒为单位
- expiress :设置超时时间 针对IE浏览器使用,以秒为单位
# 指定要清除的页面(5s过期) obj = redirect(reverse()) obj.set_cookie(key,value,max_age=5) return obj
3.补充
- key : 设置 Cookie的 键
- value : 设置 Cookie 的值
- max_age : 过期时间 , 以秒为单位
- expires :过期时间 但是是针对 IE浏览器 以秒为单位
- domain : 域名
- path : 路径
- secure : 安全组策略
- httponly : 只限制于 HTTP 请求
4)Django操作Session
- 使用Session需要迁移数据库
1.示例演示
- session主页
def home_s(request):
# 实例化、渲染form组件
login_form = loginForm()
if request.method == 'POST':
data = request.POST
username = data['username']
password = data['password']
# 模拟登录校验
if username == 'ST1' and password == '123':
request.session['login'] = 'login_true'
return redirect(reverse('home_s'))
else:
return redirect(reverse('homepage'))
return render(request, 'session/home_s.html', locals())
- 登录后才能查看的页面
def login_s(request):
# 获取登录设置的session
session = request.session.get('login')
# 校验信息
if session == 'login_true':
return render(request, 'session/login.html', locals())
else:
return redirect(reverse('home_s'))
- 退出登录
def logout_s(request):
request.session.delete()
request.session.flush()
return redirect(reverse('home_s'))
2.小结
-
设置Session
- 产生一个随机字符串
request.session['key'] = value
-
获取Session
session = request.session.get('key')
-
清除session
# 只删除服务端 request.session.delete() # 删除服务端和客户端 request.session.flush()
-
设置过期时间
- 数字:到指定s后过期
- 0:完全关闭浏览器后自动将 session删除
- 时间对象:到指定时间点自动删除
# 设置session request.session['key'] = value # 设置过期时间 request.session.set_expiry()
-
设置、获取多个session值
- 存在数据库的数据只有一条
- 但取sssion时,可通过request.session对象获取到设置的多个键值对
3.补充
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# 引擎
SESSION_CACHE_ALIAS = 'default'
# 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
# 引擎
SESSION_FILE_PATH = None
# 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
# 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
# 引擎
其他公用设置项:
SESSION_COOKIE_NAME = "sessionid"
# Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/"
# Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None
# Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False
# 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True
# 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600
# Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
# 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False
# 是否每次请求都保存Session,默认修改之后才保存(默认)
【七】CBV添加装饰器
- 给类试图函数添加装饰器需借助第三模块
from django.utils.decorators import method_decorator
0)创建装饰器
# 计时器(装饰器)
def timer(func):
def inner(*args, **kwargs):
print('args:', args) # args: (<WSGIRequest: GET '/register/'>,)
start = time.time()
take_time = func(*args, **kwargs)
end = time.time()
print("用时:", end - start, "s")
return take_time
return inner
1)给类方法加装饰器
class RegisterView(View):
@method_decorator(timer)
def get(self, request):
print(request.path)
time.sleep(1)
return render(request, 'decorator/register_dec.html', locals())
2)放到类上面
name='get'
、name='post'
@method_decorator(timer, name='get')
class RegisterView(View):
def get(self, request):
print(request.path)
time.sleep(1)
return render(request, 'decorator/register_dec.html', locals())
3)重写dispatch
- 类视图 ---> as_view() ---> 里面的 view() ---> self.dispatch()
- 因为每一个触发的类视图函数都会走 dispatch 相当于给所有人添加一个装饰器
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(
self, request.method.lower(), self.http_method_not_allowed
)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
【八】中间件
1)概念
-
Django中间件是一个第三方组件
-
对请求和响应进行处理,只有符合规定的请求和响应才能完成交互
-
在Django的settings.py配置文件中,通过MIDDLEWARE设置来定义中间件的顺序
2)作用
- 认证和授权
- 请求和响应处理
- 异常处理
- 性能优化
3)源码分析
from django.middleware.security import SecurityMiddleware
'''
class SecurityMiddleware(MiddlewareMixin):
# process_request : 处理request 请求的
def process_request(self, request):
...
# process_response : 处理视图函数返回的 response 对象的
def process_response(self, request, response):
return response
'''
from django.contrib.sessions.middleware import SessionMiddleware
'''
class SessionMiddleware(MiddlewareMixin):
# process_request : 处理request 请求的
def process_request(self, request):
...
# process_response : 处理视图函数返回的 response 对象的
def process_response(self, request, response):
return response
'''
from django.middleware.common import CommonMiddleware
from django.middleware.csrf import CsrfViewMiddleware
'''
class CsrfViewMiddleware(MiddlewareMixin):
# process_request : 处理request 请求的
def process_request(self, request):
...
def process_view(self, request, callback, callback_args, callback_kwargs):
...
# process_response : 处理视图函数返回的 response 对象的
def process_response(self, request, response):
return response
'''
from django.contrib.auth.middleware import AuthenticationMiddleware
from django.contrib.messages.middleware import MessageMiddleware
from django.middleware.clickjacking import XFrameOptionsMiddleware
4)小结
- 观察发现每一个中间件都有固定的两个请求
- process_request 处理请求进来的
- process_response 处理响应出去的
- 可选的方法
- process_view 执行视图之前会触发
5)自定义中间件
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
# if request.headers.get("Host").split(":")[0] == "localhost":
# raise Exception("非法请求")
print(" MyMiddleWare request request request 进来了 ")
def process_exception(self, request, exception):
if exception:
pass
def process_view(self, request, callback, callback_args, callback_kwargs):
print(" MyMiddleWare process_view 进来了 ")
def process_response(self, request, response):
print(" MyMiddleWare response response response 进来了")
return response
class MyMiddleWareOne(MiddlewareMixin):
def process_request(self, request):
print(" MyMiddleWareOne request request request 进来了 ")
def process_view(self, request, callback, callback_args, callback_kwargs):
print(" MyMiddleWareOne process_view 进来了 ")
def process_response(self, request, response):
print(" MyMiddleWareOne response response response 进来了")
return response
# settings.py
MIDDLEWARE = [
......
'user.middlewares.MyMiddleWare',
'user.middlewares.MyMiddleWareOne',
]
# 【一】请求进入的时候会走每一个中间件的 process_request
# process_request 走的顺序是从上至下依次走
MyMiddleWare request request request 进来了
MyMiddleWareOne request request request 进来了
# 【二】走每一个中间件的 process_view
# process_view 走的顺序是从上至下依次走
MyMiddleWare process_view 进来了
MyMiddleWareOne process_view 进来了
# 【三】进入到指定的视图函数中
/register/
<WSGIRequest: GET '/register/'>
[02/Jul/2024 04:07:59] "GET /register/ HTTP/1.1" 200 156
执行时间: 3.0085182189941406 s
# 【四】响应回去的时候走 process_response
# process_response 走的顺序是 从下至上 依次走
MyMiddleWareOne response response response 进来了
MyMiddleWare response response response 进来了
6)基于中间件开发程序 示例
send
main.py
settings.py
qq.py
wechat.py
# qq.py
class QQ():
def __init__(self):
# 初始化链接qq 的参数配置项
# 创建链接 ...
...
def send(self, content):
print("QQ发送消息:", content)
# wechat.py
class Wx():
def __init__(self):
# 初始化链接qq 的参数配置项
# 创建链接 ...
...
def send(self, content):
print("Wx发送消息:", content)
# settings.py
MODEL_LIST = [
"scripts.send_meeage.send_two.qq.QQ",
"scripts.send_meeage.send_two.wechat.Wx",
]
# main.py
import settings,importlib,os,sys
file_path = os.path.dirname(__file__)
sys.path.insert(0, file_path)
def main(content):
for path in settings.MODEL_LIST:
model_path, model_name = path.rsplit(".", maxsplit=1)
model_obj = importlib.import_module(model_path)
cls = getattr(model_obj, model_name)
obj = cls()
obj.send(content)
if __name__ == '__main__':
main(content="hello ")
【九】CSRF令牌
1)CSRF跨站请求
1.介绍
- CSRF(Cross-Site Request Forgery)跨站请求伪造是一种常见的网络攻击方式
2.保护措施
- 使用CSRF令牌
- 启用SameSite属性
- 严格验证请求来源
- 使用验证码
2)CSRF令牌验证
- CSRF校验是一种用于防止跨站请求仿造攻击的安全措施
1.签发令牌
- 每一个请求过来时都会在前端生成一个随机的令牌
{% csrf_token %}
2.form表单验证令牌
- 在form表单中添加令牌
<form action="" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="username"></p>
<p><input type="submit"></p>
</form>
3.Ajax携带CSRF
- 后端
def csrf_ajax(request):
if request.method == 'POST':
data_1 = request.POST.get('data_1')
data_2 = request.POST.get('data_2')
data_3 = request.POST.get('data_3')
data = f' 输入了{data_1},{data_2},{data_3}'
back_dict = {'code': 200, 'msg': data}
return JsonResponse(back_dict)
return render(request, 'csrf_ajax.html', locals())
- 方式一
- 在form表单遍历每一个标签获取到 键和值拼接到对象里面
<form id="form_ajax">
{% csrf_token %}
<p>Ajax携带令牌</p>
<p>输入1:<input type="text" name="data_1"></p>
<p>输入2:<input type="text" name="data_2"></p>
<p>输入3:<input type="text" name="data_3"></p>
<p><input type="button" id="button_ajax" value="提交"></p>
</form>
<script>
$(document).ready(
$('#button_ajax').click(function () {
let data = {}
$('#form_ajax').serializeArray().forEach(
function (a) {
data[a.name] = a.value
})
$.ajax({
url: "",
type: "post",
data: data,
success: function (response) {
alert(response.msg)
}
})
})
)
</script>
- 方式二
- 获取标签值
data["csrfmiddlewaretoken"] = $("input[name='csrfmiddlewaretoken']").val()
<script>
$(document).ready(
$('#button_ajax').click(function () {
let data = {}
data["csrfmiddlewaretoken"] = $("input[name='csrfmiddlewaretoken']").val()
$.ajax({
url: "",
type: "post",
data: data,
success: function (response) {
alert(response.msg)
}
})
})
)
</script>
- 方式三
- 模板取值
data["csrfmiddlewaretoken"] = "{{ csrf_token }}"
<script>
$(document).ready(
$('#button_ajax').click(function () {
let data = {}
data["csrfmiddlewaretoken"] = "{{ csrf_token }}"
$.ajax({
url: "",
type: "post",
data: data,
success: function (response) {
alert(response.msg)
}
})
})
)
</script>
- 方式四
- 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);
}
}
});
<script src="{% static 'csrf.js' %}"></script>
<script>
$(document).ready(
$('#button_ajax').click(function () {
let data = {}
$.ajax({
url: "",
type: "post",
data: data,
success: function (response) {
alert(response.msg)
}
})
})
)
</script>
4.小结
- form表单验证令牌
- 在form表单中添加令牌
- Ajax携带CSRF
- 在form表单遍历每一个标签获取到 键和值拼接到对象里面
- 获取标签值
- 模板取值
- js文件配置
【十】CSRF装饰器
- 装饰器引入
from django.views.decorators.csrf import csrf_protect, csrf_exempt
# csrf_protect 增加 csrf 验证保护
# csrf_exempt 取消 csrf 验证保护
from django.utils.decorators import method_decorator
1)全局开启 局部禁用
- 开启 django.middleware.csrf.CsrfViewMiddleware
- 局部禁用
- 只有在 CBV 视图中的 dispatch 生效 其他不生效
class CSRFView(View):
def get(self, request):
return render(request, "csrf_index.html", locals())
def post(self, request):
return HttpResponse("post")
@method_decorator(csrf_exempt) # 可以访问
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
2)全局关闭 局部开启
- 关闭 django.middleware.csrf.CsrfViewMiddleware
- 三种方法均可生效
class Deco(View):
def get(self, request, *args, **kwargs):
return render(request, 'decorator.html', locals())
@method_decorator(csrf_protect) # 无法访问
def post(self, request, *args, **kwargs):
return HttpResponse('成功进入')
@method_decorator(csrf_protect, name='post') # 无法访问
class Deco(View):
def get(self, request, *args, **kwargs):
return render(request, 'decorator.html', locals())
def post(self, request, *args, **kwargs):
return HttpResponse('成功进入')
【十一】auth模块
- 注册超级管理员
python manage.py createsuperuser
- 引入
from django.contrib import auth
from django.contrib.auth.models import User
1)校验注册
User.objects.create_user(username=username, password=password)
2)校验密码
user_obj = auth.authenticate(request, username=username, password=password)
print(user_obj)
# 正确:返回注册数据
# 错误:返回None
3)保存用户状态
if user_data:
auth.login(request,user_obj)
4)判断是否登录
print(request.user.is_authenticated())
# 正常用户返回True
# 匿名用户返回False
5)修改密码
# 修改密码
request.user.set_password(new_password)
# 保存到数据库
request.user.save()
6)注销登录
auth.logout(request)
7)扩展auth_user表
1.方式一:继承AbstractUser扩写字段
from django.db import models
from django.contrib.auth.models import User,AbstractUser
class UserInfo(AbstractUser):
new_text=models.CharField(max_length=255)
2.方式二:关联表
from django.db import models
from django.contrib.auth.models import User,AbstractUser
class UserDetail(models.Model):
new_text=models.CharField(max_length=255)
user=models.OneToOneField(to="User")
标签:59,Form,form,self,request,组件,data,response,def
From: https://www.cnblogs.com/Mist-/p/18305921