zoukankan      html  css  js  c++  java
  • Python学习笔记Day25

    ModelForm

    model和form的结合体,比form方便,但是耦合太强,不适合大规模
    参考博客

    Model + Form => 验证 + 数据库操作
    
    # 利用model.A中的字段,不用重复再写字段
    

    创建ModelForm

    from django import forms
    from django.forms import widgets as Fwidgets
    class UserInfoModelForm(forms.ModelForm):
    
        is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())     # 创建model以外的标签,用法同form的Field
    
        class Meta:             # 创建model已有的字段标签
            model = models.UserInfo
            fields = '__all__'
    
        def clean_username(self):
            old = self.cleaned_data['username']
            return old
    
    ./views.py
        obj = XXOOModelForm(request.POST)       # 提交数据
        if obj.is_valid():
            obj = form.save()                   # 默认自动保存多对多数据
        else:
            print(obj.errors['user'][0])            # 获取指定错误信息
            print(obj.errors.as_json())             # 打包为字典的错误信息
    
    ./xxx.html
        <p>{{ obj.user }} {{ obj.user.errors }}</p>
    
        {{ obj.as_p }} {{ obj.user.errors }}           # 一次性以<p>生成所有标签
        {{ obj.as_ul }} {{ obj.user.errors }}          # 一次性以<ul>生成所有标签
    
        <table>   
            {{ obj.as_table }} {{ obj.user.errors }}   # 一次性以<table>生成所有标签
        </table>
    
        {{ form.xxoo.label }}                   # label值
        {{ form.xxoo.id_for_label }}            # label的for值,id_xxx
        {{ form.xxoo.label_tag }}               # 自动生成label(包含上述两点)
        {{ form.xxoo.errors }}                  # 错误信息
    

    Meta字段

    class Meta:         # 生成HTML标签
        model = models.UserInfo         -> 对应的Model
        fields=None                     -> 字段, '__all__' => 所有字段, ['username','email']
        exclude=None                    -> 排除字段, ['username']
        labels=None                     -> 提示信息, {'username':'用户名'}
        help_texts=None                 -> 帮助提示信息, {'username':'用户名不能以数字开头...'}
        widgets=None                    -> 自定义插件, {'username':F_widgets...}
                                        => 需要从Form里导入widgets并 as ...重命名,以免和字段名重复
        error_messages=None             -> 自定义错误信息, {'username':{'required':'不能为空'},'email':{...}}
                                        => 可整体定义错误信息 {'__all__':{...}}
                                        # ? from django.core.exceptions import NON_FIELD_ERRORS
        field_classes=None              -> 自定义字段类型 (将model中定义的字段类型修改)
                                        => {'email':F_field.URLField}
        localized_fields=None           -> 本地化,如:根据不同时区显示数据, =('birth_date',)
                # 如:
                    数据库中,默认UTC时间
                        2016-12-27 04:10:57
                    需要在setting中做相应的配置
                        TIME_ZONE = 'Asia/Shanghai'
                        USE_TZ = True
                    则显示:
                        2016-12-27 12:10:57
    
    article_modelform = ArticleModelForm(label_suffix='')   -> 修改label后缀
    

    创建或修改数据

    .../views.py
    
    obj = XXOOModelForm()                   # 页面显示
    模板文件中的使用类似Form
    
    obj = XXOOModelForm(request.POST)       # 提交数据
    if obj.is_valid():
        obj = form.save()                   # 默认自动保存多对多数据
        values = obj.cleaned_data           # 获取正确数据
        return ...
    else:
        print(obj.errors.as_json())
        return ...
    
    # 拆分为三步
        obj = form.save(commit=False)
        obj.save()      # 保存单表信息
        obj.save_m2m()  # 保存关联的多对多信息
    

    更新和初始化数据

    • 修改数据GET时,传入原始数据

        obj = model.tb.objects.get(id=1)                            # 从model中获取对象
        model_form_obj = XXOOModelForm(instance=obj)                # GET时,将obj对象作为默认值传给modelFrom显示
      
    • 修改完POST时,将数据更新至当前对象,否则将新建数据而不是更新数据

        obj = model.tb.objects.get(id=1)
        model_form_obj = XXOOModelForm(request.POST,instance=obj)   # POST时,将提交的数据更新至obj对象
      

    PS: 单纯初始化

    model_form_obj = XXOOModelForm(initial={...})
    

    修改样式属性

    • 第一种方法:

        class BookForm(forms.ModelForm):
            class Meta:
                ...
                widgets = {
                    'name': Textarea(attrs={'cols': 80, 'rows': 20}),
                    'description': Textarea(attrs={'cols': 80, 'rows': 20}),
                }
      
    • 第二种重写__init__方法:

        class BookForm(forms.ModelForm):
            class Meta:
                model = Book
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.fields['name'].widget.attrs.update({'class': 'special'})
                self.fields['description'].widget.attrs.update(size='40')
      

    验证的执行过程

    *UserForm*      >>继承>>  *Form*        >>>>>>>>>>>>>>>>>>>>>>>>>>>>>继承>> *BaseForm*(is_valid...)
    
    *UserModelForm* >>继承>>  *ModelForm*   >>继承>> *BaseModelForm*   >>继承>> *BaseForm*
    

    ModelForm验证的使用方法与Form一样

    is_valid -> full_clean -> 钩子 -> 整体错误
    

    字典字段验证

    def clean_字段名(self):
        # 可以抛出异常
        # from django.core.exceptions import ValidationError
        return "新值"
    

    用于验证

    obj = XXOOModelForm()
    obj.is_valid()
    obj.errors.as_json()
    obj.clean()
    obj.cleaned_data
    

    Django ModelChoiceField前台下拉菜单显示object的解决方法

    在model中添加如下代码即可,不加的话显示就是object

    def __str__(self):
        return self.name
    

    隐藏的modelform标签,而如果该标签为required,提交时浏览器会报错

    解决办法:

    1. form表单添加novalidate属性,但会导致所有验证都不能用,不建议

    2. 取消该标签的required

  • 相关阅读:
    算法实现:在10个数中选6个数,显示所有组合
    转载:PostgreSQL和MySQL协议简介
    转载:国内外高精地图厂商一览
    使用带key访问iPortalREST服务
    cass启动提示Frame主框架程序没有加载
    设置Gridview单元格内容不换行
    Sql自定义编号唯一性问题
    关于EXCEL数据导入到SQLServer中字段存在NULL的问题
    Gridview显示网格线
    ComboBox自动匹配查找
  • 原文地址:https://www.cnblogs.com/JeromeLong/p/13252553.html
Copyright © 2011-2022 走看看