• forms组件补充与ModelForm简单使用与cookie与session


    forms组件钩子函数

    钩子函数可以让字段在原有的校验功能上在新增一个自定义校验的功能。

    局部钩子

    校验单个字段,在form类中编写一个函数:

    def clean_字段名(self):
        校验代码
        return 字段值
    

    比如:判断用户名name字段值是否存在:

    class LoginForm(forms.Form):
        name = forms.CharField(max_length=8)
    
        def clean_name(self):
            # 先获取字段值
            name = self.clean_data.get('name')
            # 判断是否存在
            is_exist = models.User.objects.filter(name=name)
            if is_exist:
                # 错误信息展示
                self.add_error('name', '用户名已存在')
            # 最后将你勾上来的name返回回去
            return name
    

    全局钩子

    校验多个字段,在form类中编写一个函数:

    def clean(self):
        校验代码
        return self.cleaned_data
    

    比如校验两个字段值是否一致:

    class LoginForm(forms.Form):
        name = forms.CharField(max_length=8)
        confirm_name = forms.CharField(max_length=8)
    
        def clean(self):
            # 先获取字段值
            name = self.clean_data.get('name')
            confirm_name = self.clean_data.get('confirm_name')
            # 判断是否一致
            if name != confirm_name:
                # 错误信息展示
                self.add_error('confirm_name', '两次用户名不一致')
            # 最后将整个数据返回
            return self.clean_data
    

    image

    forms组件字段参数

    字段参数

    参数 作用
    min_length 最小长度
    max_length 最大长度
    label 字段名称
    error_messages 错误信息展示
    min_value 最小值
    max_value 最大值
    initial 默认值
    validators 正则校验器
    widget 控制渲染出来的标签各项属性
    choices 选择类型的标签内部对应关系

    validators详解

    演示:

    from django.core.validators import RegexValidator
    class MyForm(forms.Form):
        phone = forms.CharField(
            validators=[
                RegexValidator(r'^[0-9]+$', '请输入数字'),
                RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
            ]
        )
    

    choices详解

    定义选择类型的标签内部对应关系,可以直接编写,也可以从数据库中获取。

    方式一:

    # 直接编写
    class MyForm(forms.Form):
        gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",
        )
        
    # 数据库获取数据
    class MyForm(forms.Form):
        course = forms.fields.ChoiceField(
            choices=models.Course.objects.all().values_list('id', 'name'),
            label="课程",
        )
    

    方式二:

    # 直接编写
    class MyForm(forms.Form):
        gender = forms.fields.ChoiceField(label="性别")
    
        def __init__(self, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
            self.fields['gender'].choices = ((1, "男"), (2, "女"), (3, "保密"))
            
    # 数据库获取数据
    class MyForm(forms.Form):
        course = forms.fields.ChoiceField(label="课程")
    
        def __init__(self, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
            self.fields['course'].choices = models.Course.objects.all().values_list('id', 'name')
    

    widget详解

    使用form组件生成的标签无法在前端自定义样式,只能使用widget来控制。

    基本语法:

    widgets=forms.widgets.控制type的类型(
        attrs={'属性1':'值',...}
    )
    

    比如:

    class MyForm(forms.Form):
        name = forms.CharField(
            widget=forms.widgets.TextInput(
                attr={'class':'c1'}
            )
        )
    

    文本输入框

    widget=forms.widgets.TextInput()
    

    密码输入框

    widget=forms.widgets.PasswordInput()
    

    数字输入框

    widget=forms.widgets.NumberInput()
    

    radio

    class MyForm(forms.Form):
        gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",
            widget=forms.widgets.RadioSelect()
        )
    

    单选select

    class MyForm(forms.Form):
        gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",
            widget=forms.widgets.Select()
        )
    

    多选select

    class MyForm(forms.Form):
        hobby = forms.fields.MultipleChoiceField(
            choices=((1, "read"), (2, "run"), (3, "game")),
            label="爱好",
            widget=forms.widgets.SelectMultiple()
        )
    

    单选checkbox

    class MyForm(forms.Form):
        keep = forms.ChoiceField(
            label="是否记住密码",
            widget=forms.widgets.CheckboxInput()
        )
    

    多选checkbox

    class MyForm(forms.Form):
        hobby = forms.fields.MultipleChoiceField(
            choices=((1, "read"), (2, "run"), (3, "game")),
            label="爱好",
            widget=forms.widgets.CheckboxSelectMultiple()
        )
    

    image

    forms组件字段类型

    常见字段

    字段 作用
    CharField() 文本字段
    IntegerField() 数字字段
    DecimalField() Decimal字段
    EmailField() 邮箱校验字段
    ChoiceField() 单选字段
    MultipleChoiceField() 多选字段

    其他字段

    点击查看
    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类型
    

    ModelForm简单使用

    forms组件主要配合models里面的模型类一起使用,但是模型类里面的字段需要在forms类中相当于重写一遍,代码冗余,为了更好的结合forms与models的关系,有了一个ModelForm(基于forms组件)。

    简单使用

    models:

    class User(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        addr = models.CharField(max_length=32)
    

    forms:

    class MyUser(forms.ModelForm):
        class Meta:
            model = models.User  # 指定关联的表
            fields = '__all__'  # 所有的字段全部生成对应的forms字段
            labels = {  # 每个字段标签的labels参数
                'name': '用户名',
                'age': '年龄',
                'addr': '地址'
            }
            widgets = {  # 每个字段标签的widget参数
                "name": forms.widgets.TextInput(attrs={"class": "form-control"}),
            }
    

    views:

    添加数据

    def home(request):
        form_obj = MyUser()
        if request.method == 'POST':
            if form_obj.is_valid():
                # 获取提交的数据
                form_obj = MyUser(request.POST)
                # 保存数据,向表中添加数据
                form_obj.save()
        return render(request, 'home.html', locals())
    

    编辑数据

    def home(request):
        form_obj = MyUser()
        if request.method == 'POST':
            if form_obj.is_valid():
                # 获取数据看看是否已存在
                edit_obj = models.User.objects.filter(name=request.POST.get('name')).first()
                # 新增还是保存就取决于instance参数有没有值
                form_obj = MyUser(request.POST,instance=edit_obj)
                # 保存数据
                form_obj.save()
        return render(request, 'home.html', locals())
    

    cookie与session简介

    简介

    HTTP协议中有一个特性:无状态,意思是服务端不会保存客户端的数据,客户端一直向服务端发送请求,服务端都不会认识客户端,而cookie就可以让服务端认识客户端。

    cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

    比如在一些网站中,你登陆后就不需要在登录了,这就是因为你的信息被保存在了cookie中,登录一次后,那些网站就知道你已经登录了。

    原理

    由服务器产生内容,浏览器收到后保存在cookie;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。

    image

    session

    简介

    如果数据保存在cookie中,很容易被看到,安全性太低,因此需要一个新东西,那就是session。它把数据保存在了服务端,并给客户端返回一个随机字符串保存,这个随机字符串与服务端里的数据对应。每次客户端发送请求时会携带该随机字符串,服务端会进行比对。

    django操作cookie

    基本使用

    设置cookie

    def index(request):
        res = HttpResponse('index页面')
        res.set_cookie('name', 'abcd')
        return res
    

    获取cookie

    def home(request):
        if request.COOKIE.get('name'):
            return HttpResponse('cookie有name')
        return HttpResponse('cookie中没有name')
    

    image

    进阶

    在上述例子中,如果我想要给多个视图函数添加一个判断cookie的功能,我们可以使用装饰器:

    def login_auth(func):
        def inner(request, *args, **kwargs):
            if request.COOKIES.get('name'):
                return func(request, *args, **kwargs)
            return HttpResponse('你的cookie中还没有name')
        return inner
    
  • 相关阅读:
    win11下安装linux子系统M
    轻松入门Spring MVC
    【网络安全】黑客自学笔记
    通过jsoncpp读取JSON文件
    Recommendation Fairness: From Static to Dynamic 阅读笔记
    Whale 帷幄技术周大咖分享:AI 迎来大洗牌
    【论文精读2】MVSNet系列论文详解-RMVSNet
    手持电动工具CE认证EN62841标准怎么做?
    Docker容器-------数据卷和数据卷容器及cgroups资源限制
    Alpha-Beta 剪枝
  • 原文地址:https://www.cnblogs.com/yume-zbh/p/16302208.html