首页 > 其他分享 >59.Form组件

59.Form组件

时间:2024-07-16 19:07:41浏览次数:10  
标签:59 Form form self request 组件 data response def

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

相关文章

  • sqldumper.exe 是 SQL Server 的一个重要组件,专门用于捕获和处理关键错误,帮助管理员和
     sqldumper.exe的起源可以追溯到MicrosoftSQLServer的开发和运行时管理中。它作为SQLServer的一部分,主要用于处理数据库引擎遇到的关键错误和异常情况。具体来说,sqldumper.exe主要功能包括:异常处理和故障捕获:当SQLServer数据库引擎遇到严重错误时,如内存访问错误......
  • Laravel 组件
    创建组件命令phpartisanmake:componentAlertmake:component命令还将为组件创建视图模板。视图将放在resources/views/components目录中。为自己的应用程序编写组件时,组件会在app/View/components目录和resources/views/components目录中自动发现,因此通常不需要进一步......
  • 代码随想录算法训练营第九天 | 151.翻转字符串里的单词、卡码网:55.右旋转字符串、28.
    151.翻转字符串里的单词题目:.-力扣(LeetCode)思路:用快慢双指针重置空格,先整体翻转再局部翻转代码:classSolution{public:voidremoveSpace(string&s){intslow=0;for(intfast=0;fast<s.size();fast++){if(slow!=0&&s[fast]!='')......
  • vue2 简洁的行政区划选择组件封装
     vue2简洁的行政区划选择组件封装//判断变量是否为null或undefinedexportfunctionisNullOrEmpty(value){ returnvalue===null||value===undefined||value===''}//判断变量是否为null或undefinedexportfunctionisNullOrUndefined(value){ ret......
  • PHPStudy搭建xssplatform
    1、源码下载https://github.com/78778443/xssplatform2、安装配置修改配置文件 index.php    新建.htaccess文件<IfModulemod_rewrite.c>RewriteEngineOnRewriteBase/RewriteRule^([0-9a-zA-Z]{6})$/index.php?do=code&urlKey=$1[L]RewriteRule^do/auth/(......
  • 2024-07-16 记录vue内置组件(ps:内容来自GPT)
    1. Transition和TransitionGroup用途:用于为单个元素或组件提供过渡效果。TransitionGroup则用于列表中的多个元素或组件的过渡效果。特点:Transition:只影响单个元素或组件,不会额外渲染DOM元素。TransitionGroup:渲染一个真实的DOM元素(默认为<span>),可以通过tag属性改变渲染......
  • winform 动态截断或者补全文字宽度
    使用TabControl时,发现它的选项卡宽度会随文字长度变化,我自己做了一个浏览器,发现很难看,于是写了上算法,对文字长度进行填充或截断,效果很不错: 调用代码:using(varg=tabs.CreateGraphics()){tabPage.Text=""+PadAndEllipsis(g,tabs.Font,title,150)+""......
  • bluz glib编程 --- GVariant Format Strings 介绍
    GVariantFormatStrings类型字符串实例分析(sa{sv}as)外层是元组类型,内含三个成员,分别是字符串s字典类型数组a{sv},字符串作为key,variant作为value字符串类型数组as(i@ii)外层是元组类型,内含三个成员,分别是gint类型数字类型ivariant类型@i,对应数字......
  • 深入探讨React表单组件:从基础到高级
    深入探讨React表单组件:从基础到高级大家好!今天我们来聊聊React中的表单组件。表单在前端开发中是非常常见的需求,无论是登录、注册还是数据提交,表单组件都扮演着重要的角色。本文将带你从基础到高级,深入了解React表单组件的使用和优化。基础知识在React中,表单元素(如<input>、<te......
  • 论 Suspense 组件在 Vue 3 中的重要性
        大家好,我是CodeQi! 一位热衷于技术分享的码仔。你是否曾经遇到过在加载大量数据时,界面卡顿或是空白的问题?如果你正在开发一个复杂的前端项目,那么一定需要处理很多异步数据请求。而异步请求太多就会导致用户看到空白屏幕时间变长,这对用户体验非常不友好。......