ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

day59

2019-12-03 20:03:48  阅读:311  来源: 互联网

标签:obj form models forms day59 length class


目录

多对多三种建表方式

  1. 全自动

    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四个操作

    缺点:

    • 自动创建的第三张关系表无法扩展和修改字段,表的扩展性较差
  2. 纯手动

    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)

    优点:

    • 第三张表中所有字段都可以自己定义

    缺点:

    • 不再支持跨表查询,不再有正反向的概念
    • 没有了add/remove/set/clear四个操作
  3. 半自动

    class Book(models.Model):
     title = models.CharField(max_length=32)
     # 多对多关系字段
     authors =   models.ManyToManyField(
         to='Authors',
         through='Book2Author',
         through_fields=("book","authors")
     )
    
    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')
    
    '''
    当你的ManyToManyField只有一个参数to的情况下,orm会自动帮你创建第三张表;
    如果你加了through和through_fileds那么orm就不会自动帮你你创建,但是会在内部帮你维护关系,让你能够继续使用orm的跨表查询
    '''

    优点:

    • 可以添加修改第三张关系表中的字段
    • 支持orm跨表查询

    缺点:

    • 不支持add/remove/set/clear四个操作

FORM组件

主要功能:

  • 生成可用的HTML标签
  • 对用户提交的数据进行校验
  • 保留上次输入的内容

前提

from django import forms

#需要先定义一个类
class MyForm(forms.Form):
    
    username = forms.CharField(max_length=8,min_length=3)
    
    password = forms.CharField(max_length=8,min_length=3)
    # email字段 必须是邮箱格式
    email = forms.EmailField()

前端校验数据

# 实例化类
form_obj = views.MyForm({'username':'jason','password':'12','email':'123'})

# 查看校验的数据是否合法
form_obj.is_valid()

# 查看不符合规则的字段及错误的理由
form_obj.errors

# 查看符合规则的字段的数据
form_obj.cleaned_data

# 传值数量
'''
因为是由类的字段向实例化对象字段的映射,所以不能少传;但是多传的话,多传的字段不会进行校验
'''

渲染标签

forms组件只会帮你渲染获取用户输入的标签,不会渲染提交按钮

  1. 方式一:封装程度太高,不推荐使用,可以用在本地测试

    {{ form_obj.as_p }}  <!--自动渲染所有input框  -->
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}
  2. 方式二:不推荐使用

    {{ form_obj.username.label }}{{ form_obj.username }}
    {{ form_obj.username.label }}{{ form_obj.password }}
    {{ form_obj.username.label }}{{ form_obj.email }}
  3. 方式三:推荐使用

    {% for form in form_obj %}
     <!--form 等价于你方式2中的对象点字段名-->
     <p>{{ form.label }}{{ form }}</p>  
    
    {% endfor %}

展示信息

<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 action="" method="post" novalidate>

内置校验器

from django.core.validators import RegexValidator
#validators作为字段参数
validators=[
    RegexValidator(r'^[0-9]+$', '请输入数字'),
    RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),
]

自定义校验器

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定义验证规则
def mobile_validate(value):
    mobile_re = re.compile(
        r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
    )
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
 
 
class PublishForm(Form):
 
 
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '标题不能为空',
                                            'min_length': '标题最少为5个字符',
                                            'max_length': '标题最多为20个字符'},
                            widget=widgets.TextInput(
                                attrs={'class': "form-control",
                                       'placeholder': '标题5-20个字符'}
                            ))
 
 
    # 使用自定义验证规则
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手机不能为空'},
                            widget=widgets.TextInput(
                                attrs={'class': "form-control",
                                       'placeholder': u'手机号码'}
                            ))
 
    email = fields.EmailField(required=False,
                            error_messages={
                                'required': u'邮箱不能为空',
                                'invalid': u'邮箱格式错误'
                            },
                            widget=widgets.TextInput(
                                attrs={'class': "form-control", 
                                       'placeholder': u'邮箱'
                                      }
                            ))

HOOK方法

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"})
    )
    ...
    # 定义局部钩子,用来校验username字段
    def clean_username(self):
        value = self.cleaned_data.get("username")
        if "666" in value:
            raise ValidationError("光喊666是不行的")
        else:
            return value
class LoginForm(forms.Form):
    ...
    password = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(
                    attrs={'class': 'form-control'}, 
                    render_value=True)
                )
    re_password = forms.CharField(
        min_length=6,
        label="确认密码",
        widget=forms.widgets.PasswordInput(
                    attrs={'class': 'form-control'}, 
                    render_value=True)
                )
    ...
    # 定义全局的钩子,用来校验密码和确认密码字段是否相同
    def clean(self):
        password_value = self.cleaned_data.get('password')
        re_password_value = self.cleaned_data.get('re_password')
        if password_value == re_password_value:
            return self.cleaned_data
        else:
            self.add_error('re_password', '两次密码不一致')
            raise ValidationError('两次密码不一致')

常用字段和插件(了解即可)

#默认值
initial='默认值'

#重写错误信息
error_messages={
    'requeire':'不能为空',
    'invalid':'格式错误',
    'min_length':'用户名最短8位',
}

#修改标签类
widget = forms.widgets.PasswordInput(attrs={'class':'c1 c2'})

更多

标签:obj,form,models,forms,day59,length,class
来源: https://www.cnblogs.com/shenblog/p/11978982.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有