django中Form和ModelForm组件

目录

一、Form组件

1、form作用

1、生成HTML标签

2、携带数据、 显示默认值(initial),做编辑页面显示默认值。

3、数据校验,对用户提交的数据格式校验

2、form校验流程

3、form字段的类型

1、forms.ChoiceField()

2、forms.CharField()

4、form字段参数

5、注意事项

6、form.errors是一个dict对象,里面有很多方式,默认是ul>li

7、validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],正则表达式

二、ModelForm组件

  1、modelform组件由于对单表的操作

2、ModelForm提供的功能

1、不编写字段,直接引用Model字段【优秀】

2、生成HTML标签 + 插件 + 和 参数的配置,基于BootStrap样式优化

3、表单的验证

4、保存(新增、更新,多于或少于生产字段)

三、super关键字

四、BootStrap样式优化

1、forms.Form:

2、forms.ModelForm:

3、super关键字

4、BootStrap样式优化

五、form或modelForm显示默认值

1、form显示默认值

2、modelform显示默认值

六、modelForm数据关联和校验方式

1、利用modelForm来实现关联数据(关联字段的跨表)

1、方式一:数据库表结构

2、方式二:bootstrapt样式化(self.fields['level'].queryset对象)

2、modelform校验方式

1、数据库表结构校验

2、modelform校验

七、modelform自定义插件补充


一、Form组件

1、form作用

1、生成HTML标签

- 保留原来提交的数据,不再担心form表单提交时页面刷新。
 

class LoginForm(forms.Form):
    role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )

    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "用户名"})
    )

    password = forms.CharField(
        label="密码",
        min_length=6,
        max_length=10,
        validators=[RegexValidator(r'^[0-9]+$', '密码必须是数字'), ],  # 正则表达式
        widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "密码"}, render_value=True)
    )

2、携带数据、 显示默认值(initial),做编辑页面显示默认值。

在传入initial来指定html默认显示的值

#在传入initial时来指定默认显示的值
form=LoginForm(initial={"role":"xx","username":"xxx","password":"xxxx"})

3、数据校验,对用户提交的数据格式校验

form = LoginForm(data=request.POST)
if form.is_valid():
    print(form.cleaned_data)
else:
    print(form.errors)

2、form校验流程

  • 每个字段的内部:required + validators + min_length=6,max_length=10

  • 字段的钩子方法

  • def clean_username(self):
        user = self.cleaned_data['username']
        # 校验规则
        # 校验失败
        if len(user) < 3:
            from django.core.exceptions import ValidationError
            raise ValidationError("用户名格式错误")
    	return user
    
    print(form.cleaned_data)
  • clean(不管前面的字段有么有校验通过,都会执行)

  • def clean(self):
        # 对所有值进行校验
        from django.core.exceptions import ValidationError
        # 1.不返回值,默认 self.cleaned_data
        # 2.返回值,self.cleaned_data=返回的值
        # 3.报错,ValidationError ->  self.add_error(None, e)
  • _post_clean

    • def _post_clean(self):
          pass

注意:在每个字段的钩子方法中,只有上一个字段校验通过后,才能在当前字段调用之前的字段,self.cleaned_data才会有字段

from django import forms

class SmsLoginForm(forms.Form):
    role = forms.ChoiceField()

    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "手机号"})
    )

    code = forms.CharField()


    def clean_code(self):
        mobile = self.cleaned_data.get('mobile')
        code = self.cleaned_data['code']
        if not mobile:
            return code

3、form字段的类型

1、forms.ChoiceField()

#Choice类型
role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )

2、forms.CharField()

    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "手机号"})
    )

4、form字段参数

1、字段的label,label="角色",模板调用label用法<label for="{{ field.id_for_label }}">

2、当前字段的名字,field.name

3、required=True,必填项

4、 min_length=6,max_length=10,表示长度大于6小于10

5、widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "密码"}, render_value=True),自定义的插件,加入html的css样式

6、validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],正则表达式

from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError

7、help_text="填入0-100整数表示百分比,例如:90,表示90%",模板的提示

8、

5、注意事项

1、校验通过的字段才会在self.cleaned_data,

2、clean报错,self.add_error(none,"error")

取值,

python中:form.errors.__all__.0

 模板语言中: form.non_field_errors()  <==> form.errors.__all__

6、form.errors是一个dict对象,里面有很多方式,默认是ul>li

7、validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],正则表达式

二、ModelForm组件

  1、modelform组件由于对单表的操作

class LevelModelForm(forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']

1、forms.ModelForm返回self.fields里面是字典{"title":"xxx","percent":"xxxxx"}

2、只会生成filds里面的字段

3、也可以对生成的字段进行重写

4、生成的字段是根据数据库的类型生成

5、widet里面默认的是inputtext类型

2、ModelForm提供的功能

1、不编写字段,直接引用Model字段【优秀】

1、字段选择分为三类: fields = "__all__",exclude = ['active'],fields = ['title', 'percent']

class LevelModelForm(forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']
        fields = "__all__"
		exclude = ['active']


class LevelModelForm(BootStrapForm, forms.ModelForm):
    xxx = forms.CharField(label='xxx')

    class Meta:
        model = models.Level
        # fields = "__all__"
        # exclude = ['active']
        fields = ['title', 'xxx', 'percent', ]


class LevelModelForm(BootStrapForm, forms.ModelForm):
    title = forms.ChoiceField(label='xxx', choices=((1, "xxx"), (2, "xxxxxx")))

    class Meta:
        model = models.Level
        # fields = "__all__"
        # exclude = ['active']
        fields = ['title', 'percent', ]

2、生成HTML标签 + 插件 + 和 参数的配置,基于BootStrap样式优化

from django.shortcuts import render, redirect
from web import models
from django import forms
from django.urls import reverse


class BootStrapForm:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # {'title':对象,"percent":对象}
        for name, field in self.fields.items():
            field.widget.attrs['class'] = "form-control"
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)


class LevelForm(BootStrapForm, forms.Form):
    title = forms.CharField(
        label="标题",
        required=True,
    )
    percent = forms.CharField(
        label="折扣",
        required=True,
        help_text="填入0-100整数表示百分比,例如:90,表示90%"
    )


class LevelModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']

1、用到super继承关系,super是按照类的继承关系从下往上找

2、moder.form执行完会返回一个fields的字典,包括所有的字段:对象

3、表单的验证

1、和form验证一样

class LevelModelForm(BootStrapForm, forms.ModelForm):
    title = forms.CharField(validators=[])
    class Meta:
        model = models.Level
        fields = ['title', 'percent', ]

    def clean_percent(self):
        value = self.cleaned_data['percent']
        return value


4、保存(新增、更新,多于或少于生产字段)

1、增加(基于save)

form = LevelModelForm(data=request.POST)
form.save()

2、更新(基于save)

#需要传入从数据库获取的对象
form = LevelModelForm(data=request.POST,instance=对象)
form.save()

3、自己增加值(生成的字段小于数据库必填的数据)

form = LevelModelForm(data=request.POST) # 或有 ,install=对象

form.instance.percent = 10#(自己增加值)
form.save()

4、生成的字段大于数据库必填的数据(和数据库的字段匹配的添加,不匹配的数据不管)

class LevelModelForm(BootStrapForm, forms.ModelForm):
    confirm_percent = forms.CharField(label="确认")

    class Meta:
        model = models.Level
        fields = ['title', 'percent']
        

def level_add(request):
    if request.method == "GET":
        form = LevelModelForm()
        return render(request, 'form.html', {"form": form})

    form = LevelModelForm(data=request.POST)
    if not form.is_valid():
        return render(request, 'form.html', {"form": form})

    # {'title': '1', 'percent': 2, 'confirm_percent': '3'}
    print(form.cleaned_data)
    # form.instance.percent = 10
    form.save()

    return redirect(reverse('level_list'))

三、super关键字

根据类的MRO(类的继承关系)顺序,从下到上去找。

扩展:Python中的类的继承关系是通过 c3算法 计算出来。

四、BootStrap样式优化

思考:无论在使用Form和ModelForm时,想要让页面好看,就需要将每个字段的插件中给他设置form-control样式。

1、forms.Form:

class LevelForm(forms.Form):
    title = forms.CharField(
        label="标题",
        required=True,
        # widget=forms.TextInput(attrs={"class": "form-control", 'placeholder': "请输入标题"}),
    )
    percent = forms.CharField(
        label="折扣",
        required=True,
        help_text="填入0-100整数表示百分比,例如:90,表示90%"
    )

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        
        # {'title':对象,"percent":对象}
        for name,field in self.fields.items():
            field.widget.attrs['class'] = "form-control"
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)

2、forms.ModelForm:
 

class LevelModelForm(forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']
        
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        
        # {'title':对象,"percent":对象}
        for name,field in self.fields.items():
            field.widget.attrs['class'] = "form-control"
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)

3、super关键字

根据类的MRO(类的继承关系)顺序,从下到上去找。

4、BootStrap样式优化

from django.shortcuts import render, redirect
from web import models
from django import forms
from django.urls import reverse


class BootStrapForm:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # {'title':对象,"percent":对象}
        for name, field in self.fields.items():
            field.widget.attrs['class'] = "form-control"
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)


class LevelForm(BootStrapForm, forms.Form):
    title = forms.CharField(
        label="标题",
        required=True,
    )
    percent = forms.CharField(
        label="折扣",
        required=True,
        help_text="填入0-100整数表示百分比,例如:90,表示90%"
    )


class LevelModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']

五、form或modelForm显示默认值

1、form显示默认值

form = LevelForm(initial={'title': "xxx"})

2、modelform显示默认值

level_object = models.Level.objects.filter(id=pk).first()
form = LevelModelForm(instance=level_object)

六、modelForm数据关联和校验方式

1、利用modelForm来实现关联数据(关联字段的跨表)

1、方式一:数据库表结构
level = models.ForeignKey(verbose_name="级别", to="Level", on_delete=models.CASCADE, limit_choices_to={'active': 1})
2、方式二:bootstrapt样式化(self.fields['level'].queryset对象)
#1、BootStrapForm样式
class BootStrapForm:
    exclude_filed_list = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # {'title':对象,"percent":对象}
        for name, field in self.fields.items():
            if name in self.exclude_filed_list:
                continue
            field.widget.attrs['class'] = "form-control"
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)



2、modelforms类
class CustomerModelForm(BootStrapForm, forms.ModelForm):
    exclude_filed_list = ['level']

    confirm_password = forms.CharField(
        label="重复密码",
        widget=forms.PasswordInput(render_value=True)
    )

    class Meta:
        model = models.Customer
        fields = ["username", 'mobile', 'password', 'confirm_password', 'level']
        widgets = {
            'password': forms.PasswordInput(render_value=True),
            'level': forms.RadioSelect(attrs={'class': "form-radio"})
        }

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 此处可能用到 request
        self.fields['level'].queryset = models.Level.objects.filter(active=1)

2、modelform校验方式

1、数据库表结构校验
    mobile = models.CharField(verbose_name="手机号", max_length=11, 
db_index=True, validators=[RegexValidator(r'^\d{11}$', '手机号格式错误'), ],)
2、modelform校验

和form校验一样

七、modelform自定义插件补充

针对自定义插件:

class ChargeModelForm(BootStrapForm, forms.ModelForm):
    # 静态变量
    charge_type = forms.TypedChoiceField(
        label="类型",
        choices=[(1, "充值"), (2, "扣款")],  # 只适合固定的数据,不适合去数据表中数据
        coerce=int
    )

    class Meta:
        model = models.TransactionRecord
        fields = ['charge_type', 'amount']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # self.fields['charge_type'].choices = [(1, "充值"), (2, "扣款")]  # 只适合固定的数据,不适合去数据表中数据
        # self.fields['creator'].choices = models.Administrator.objects.filter(id__gt=1).values_list("id", 'username')

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值