• form 组件


    多对多三种创建方式

    全自动:

    class Book(models.Model):
      title = models.CharField(max_length=32)
      # 多对多关系字段
      authors = models.ManyToManyField(to='Authors')

    class Authors(models.Model):
      name = models.CharField(max_length=32)

    好处:
      至始至终你都没有操作第三张表 全部都是由orm自动帮你创建的
      还内置了四个操作第三张表的方法
        add
        remove
        set
        clear
    不足:
      自动创建的第三张表无法扩展个修改字段 表的扩展性较差

    纯手撸:

    class Book(models.Model):
      title = models.CharField(max_length=32)

    class Authors(models.Model):
      name = models.CharField(max_length=32)

    class Book2Authors(models.Model):
      book = models.ForeignKey(to="Book")
      author = models.ForeignKey(to="Authors")
      create_time = models.DateField(auto_now_add = True)

    好处:
      第三张表中字段个数和字段名称全都可以自己定义
    不足:
      不再支持orm跨表查询 不再由正反向的概念
      add
      remove
      set
      clear

    半自动:

    class Book(models.Model):
      title = models.CharField(max_length=32)
      # 多对多关系字段
      authors = models.ManyToManyField(to='Authors',through='Book2Author',through_fields=("book","authors"))


    """
    当你的ManyToManyField只有一个参数to的情况下 orm会自动帮你创建第三张表
    如果你加了through和through_fields那么orm就不会自动帮你创建第三张表 但是它会在内部帮你维护关系 让你能够继续使用orm的跨表查询
    through 自己指定第三张关系表
    through_fields 自己指定第三张关系表中 到底哪两个字段维护者表与表之间的多对多关系
    """

    class Authors(models.Model):
      name = models.CharField(max_length=32)
      # 多对多关系字段 等价
      books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=("authors","book"))

    class Book2Author(models.Model):
      book = models.ForeignKey(to='Book')
      authors = models.ForeignKey(to='Authors')

      # 该表中可以由任意多的外键字段
      # 可以扩展任意的字段
    好处:
      可以任意的添加和修改第三张表中的字段
      并且支持orm跨表查询
    不足:
      不支持
      add
      remove
      clear
      set

    form组件校验数据

    使用forms组件的前提是 你需要提前写一个类
      from django import forms


      class MyForm(forms.Form):
        # username字段 最少三位 最多八位
        username = forms.CharField(max_length=8,min_length=3)
        # password字段 最少三位 最多八位
        password = forms.CharField(max_length=8,min_length=3)
        # email字段 必须是邮箱格式
        email = forms.EmailField()

    校验数据
      # 1.给写好的类 传字典数据(待校验的数据)
      form_obj = views.MyForm({'username':'jason','password':'12','email':'123'})
      # 2.如何查看校验的数据是否合法
      form_obj.is_valid()
      False # 只有当你的数据全部符合校验规则的情况下 结果才是True 否则都为False
      # 3.如何查看不符合规则的字段及错误的理由
      form_obj.errors
      {
      'password': ['Ensure this value has at least 3 characters (it has 2).'],
      'email': ['Enter a valid email address.']
      }
      # 4.如何查看符合校验规则的数据
      form_obj.cleaned_data
      {'username': 'jason'}
      # 5.forms组件中 定义的字段默认都是必须传值的 不能少传
      form_obj = views.MyForm({'username':'jason','password':'12345'})
      form_obj.is_valid()
      False
      form_obj.errors
      {'email': ['This field is required.']}
      # 6.forms组件只会校验forms类中定义的字段 如果你多传了 不会有任何影响
      form_obj = views.MyForm({'username':'jason','password':'12345','email':'123@qq.com','xxx':'嘿嘿嘿'})
      form_obj.is_valid()
      True

    form组件渲染标签

    forms组件只会帮你渲染获取用户输入的标签 不会帮你渲染提交按钮 需要你自己手动添加

    <p>forms组件渲染标签方式1:封装程度态高 不推荐使用 但是可以用在本地测试</p>
    {{ form_obj.as_p }} <!--自动渲染所有input框 -->
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}


    <p>forms组件渲染标签方式2:不推荐使用 写起来太烦了</p>
    {{ form_obj.username.label }}{{ form_obj.username }}
    {{ form_obj.username.label }}{{ form_obj.password }}
    {{ form_obj.username.label }}{{ form_obj.email }}


    <p>forms组件渲染标签方式3:推荐使用 </p>
    {% for form in form_obj %}
    <p>{{ form.label }}{{ form }}</p> <!--form 等价于你方式2中的对象点字段名-->
    {% endfor %}

    form组件展示信息

    数据的校验通常前后端都必须有
    但是前端的校验可有可无 并且弱不禁风
    后端的校验必须要有 并且必须非常的全面
    如何告诉浏览器不做校验 form表单中加一个novalidate参数即可
      <form action="" method="post" novalidate>

    def index(request):
        # 渲染标签 第一步 需要生成一个空的forms类的对象
        form_obj = MyForm()
        # 如何校验前端用户传入的数据
        if request.method == 'POST':
            # 获取用户的数据  request.POST中  forms组件校验数据
            form_obj = MyForm(request.POST)  # 改变量名一定要跟上面的form_obj变量名一直
            if form_obj.is_valid():  # 研究forms组件入口就是is_valid()
                print(form_obj.cleaned_data)
                return HttpResponse('数据全部OK')
        # 直接将生成的对象 传递给前端页面
        return render(request,'index.html',locals())
    <p>forms组件渲染标签方式3:推荐使用 </p>
    <form action="" method="post" novalidate>
        {% for forms in form_obj %}
        <p>
            {{ forms.label }}{{ forms }}
            <span>{{ forms.errors.0 }}</span>
        </p>  <!--form 等价于你方式2中的对象点字段名-->
        {% endfor %}
        <input type="submit">
    </form>

    form组件自定义校验

    内置的校验器
    from django.core.validators import RegexValidator


    validators=[
      RegexValidator(r'^[0-9]+$', '请输入数字'),
      RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),
    ]

    钩子函数 HOOK
    当你觉得上面的所有的校验还不能够满足你的需求 你可以考虑使用钩子函数
    是一个函数 函数体内你可以写任意的校验代码


    局部钩子
    你想校验单个字段

    全局钩子
    你想校验多个字段

    class MyForm(forms.Form):
        # username字段 最少三位 最多八位
        username = forms.CharField(max_length=8,min_length=3,label='用户名',initial='默认值',
                                   error_messages={
                                       'max_length':'用户名最长八位',
                                       'min_length':'用户名最短三位',
                                       'required':'用户名不能为空'
                                   },required=False,
                                   widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})
                                   )
        # password字段 最少三位  最多八位
        password = forms.CharField(max_length=8,min_length=3,label='密码',
                                   error_messages={
                                       'max_length': '密码最长八位',
                                       'min_length': '密码最短三位',
                                       'required': '密码不能为空'
                                   },widget=forms.widgets.PasswordInput()
                                   )
        confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码',
                                   error_messages={
                                       'max_length': '确认密码最长八位',
                                       'min_length': '确认密码最短三位',
                                       'required': '确认密码不能为空'
                                   },
                                   )
        # email字段 必须是邮箱格式
        email = forms.EmailField(label='邮箱',error_messages={
                                'required':'邮箱不能为空',
                                'invalid':'邮箱格式错误'
        })
    
    
        # 校验用户名中不能含有666     局部钩子
        def clean_username(self):
            username = self.cleaned_data.get('username')
            if '666' in username:
                # 给username所对应的框展示错误信息
                self.add_error('username','光喊666是不行的')
            # 将username数据返回
            return username
    
        # 校验密码 确认密码是否一致     全局钩子
        def clean(self):
            password = self.cleaned_data.get("password")
            confirm_password = self.cleaned_data.get("confirm_password")
            if not password == confirm_password:
                self.add_error('confirm_password','两次密码不一致')
            # 将全局的数据返回
            return self.cleaned_data

     补充知识点

    其他字段及参数
      label input对应的提示信息
      initial input框默认值
      required 默认为True是必填字段,用来控制字段是否必填
      widget 给input框设置样式及属性
      widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})
      widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2','username':'jason'})
      widget=forms.widgets.PasswordInput()密文

     

        # radioselect
        # 单radio值为字符串
        gender = forms.ChoiceField(
            choices=((1, ""), (2, ""), (3, "保密")),
            label="性别",
            initial=3,
            widget=forms.widgets.RadioSelect()
        )
    
        # 单选select
        hobby = forms.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=3,
            widget=forms.widgets.Select()
        )
        
        # 多选select
        hobby1 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.SelectMultiple()
        )
        
        # 单选checkbox
        keep = forms.ChoiceField(
            label="是否记住密码",
            initial="checked",
            widget=forms.widgets.CheckboxInput()
        )
        
        # 多选checkbox
        hobby2 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )
  • 相关阅读:
    26 转义符 re模块 方法 random模块 collection模块的Counter方法
    25 正则表达式
    24 from 模块 import 名字
    24 from 模块 import 名字
    24 from 模块 import 名字
    23 析构方法 items系列 hash方法 eq方法
    21 isinstance issubclass 反射 _str_ _new_ _len_ _call_
    20 属性, 类方法, 静态方法. python2与python3的区别.
    python(1)
    python之字符串格式化
  • 原文地址:https://www.cnblogs.com/fjn839199790/p/11977751.html
Copyright © 2020-2023  润新知