Django-Form组件-forms.ModelForm

Posted jjzz1234

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django-Form组件-forms.ModelForm相关的知识,希望对你有一定的参考价值。

froms.ModelForm

具有models操作数据库字段的功能,还具有Form的功能。较Form组件而言,根据model自动生成Form。

使用注册的案例进行初步认识

# 使用ModelForm创建Form模板

from django import forms
class RegForm(forms.ModelForm):
    re_password = forms.CharField(min_length=6,
                                  widget=forms.PasswordInput(attrs='placeholder': '确认密码', 'autocomplete': 'off'),
                                  label='确认密码', )

    class Meta:
        model = models.UserProfile
        fields = '__all__'
        ecclude = ['is_active', 'memo']

        min_lengths = 'password': 6
        
        # 定义字段的widgets属性
        widgets = 
            'username': forms.EmailInput(attrs='placeholder': '用户名', 'autocomplete': 'off'),
            'password': forms.PasswordInput(attrs='placeholder': '密码', 'autocomplete': 'off'),
            'name': forms.TextInput(attrs='placeholder': '姓名', 'autocomplete': 'off'),
            'mobile': forms.TextInput(attrs='placeholder': '手机号', 'autocomplete': 'off'),
        
        
        # 定义每一个字段的labels属性
        labels = 
            'username': '用户名',
            'password': '密码',
            'name': '姓名',
            'mobile': '手机号',
            'department': '部门'
        
    # 可以使用局部钩子
    def clean_mobile(self):
        phone = self.cleaned_data.get('mobile')
        ret = re.match(r"^1[35678]\d9$", phone)
        if ret:
            return phone
        else:
            raise ValidationError('手机格式不正确')

    def clean_username(self):
        user = self.cleaned_data.get('username')
        obj = models.UserProfile.objects.get(username=user)
        if obj:
            raise ValidationError('该用户已存在')
        return user
        
    # 可以定义全局钩子
    def clean(self):
        self._validate_unique = True  # 去数据库检验唯一性
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if password == re_password:
            md5 = hashlib.md5()
            md5.update(password.encode('utf-8'))
            self.cleaned_data['password'] = md5.hexdigest()
            return self.cleaned_data
        self.add_error('re_password', '两次密码不一致')  # 将全局的错误信息添加到字段错误列表中
        raise ValidationError('两次密码不一致')

在views视图函数中进行实例化

def reg(request):
    form_obj = RegForm()
    if request.method == 'POST':
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():   
            form_obj.save()
            return redirect('app01:login')
    return render(request, 'logon.html', 'form_obj': form_obj)

在htm中进行展示

<form action="" method="post">
    % csrf_token %
    <div># 注册账户 #
         form_obj.username    form_obj.username.errors.0 
    </div>
    <div># 注册密码 #
         form_obj.password    form_obj.password.errors.0 
    </div>
    <div># 密码确认 #
         form_obj.re_password    form_obj.re_password.errors.0 
    </div>
    <div># 真实姓名 #
         form_obj.name    form_obj.name.errors.0 
    </div>
    <div># 注册部门 #
         form_obj.department    form_obj.department.errors.0 
    </div>
    <div># 注册手机号 #
         form_obj.mobile    form_obj.mobile.errors.0 
    </div>
    <div>
         error 
    </div>
    <button id="submit">Sign on</button>
</form>

知识点-class Meta

class Meta是一个内部类,作用是定义Form模型的特殊性质

class Meta中常用的参数有:

model = models.UserProfile  # 根据一个具体的model表进行form的创建
fields = "__all__"  # 字段,如果是__all__,就是表示列出所有的字段
exclude = None  # 排除的字段
labels = None  # 提示信息
help_texts = None  # 帮助提示信息
widgets = None  # 自定义插件
error_messages = None  # 自定义错误信息
field_classes=None   # 自定义字段类 (也可以自定义字段)

知识点-验证和其他

# views中进行写入验证
form_obj.is_valid()  # 数据库保存数据之前,判断该条记录能否写入

# vies中进行保存
form_obj.save()

# 可以重写全局钩子和局部钩子

# 全局钩子中
self._validate_unique = True  # 去数据库检验进行unique判断,不设置时会有唯一性异常

数据添加和修改中的应用

路由

url(r'^customer_add/', views.customer_operate,name='customer_add'),
url(r'^customer_edit/(\d+)/', views.customer_operate,name='customer_edit'),

视图函数

def customer_operate(request, pk=None):
    obj = models.Customer.objects.filter(pk=pk).first()
    form_obj = OperateForm(instance=obj)
    if request.method == 'POST':
        form_obj = OperateForm(request.POST, instance=obj)
        if form_obj.is_valid():
            form_obj.save()  # save
            next = request.GET.get('next')
            if next:
                return redirect(next)
            return redirect('app01:mine_customer')
    title = '编辑客户信息' if pk else '添加用户信息'
    return render(request, 'customeroperate.html', 'form_obj': form_obj, 'title': title)

ModelForm

class BaseForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 自定义操作,循环添加class操作,当遇到MultiSelectFormField或者forms.BooleanField框时,不加class类
        for name, field in self.fields.items():
            # if name == 'course'  # 可以直接判断字段名
            if isinstance(field, (MultiSelectFormField, forms.BooleanField)):
                # 判断字段类型是MultiSelectFormField, forms.BooleanField还可以根据需求继续添加到元组中,让他们的格式不接受form-control的样式
                continue
            # 方式一:
            field.widget.attrs['class'] = 'form-control'
            # 方式二:
            # field.widget.attrs.update('class': 'form-control')


# 新增和编辑客户form组件
class OperateForm(BaseForm):

    class Meta:
        model = models.Customer
        fields = '__all__'

html中

<form class="form-horizontal" action="" method="post" novalidate >
      % csrf_token %
      % for customer in form_obj %

     <div class="form-group % if customer.errors % has-error % endif %">
           <label for="customer.id_for_label"
                           class="col-sm-3 control-label % if not customer.field.required % not_required % endif %">
                            customer.label</label>
          <div class="col-sm-4">
                         customer 
                    </div>
                    <p class="col-sm-4"><span> customer.errors.0 </span></p>

           </div>
                % endfor %

           <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <button type="submit" class="btn btn-primary">保存</button>
                    </div>
                </div>
            </form>

以上是关于Django-Form组件-forms.ModelForm的主要内容,如果未能解决你的问题,请参考以下文章

Django-form组件补充

Python学习-django-Form组件

Django-Form组件之字段

Django-Form组件-forms.ModelForm

python3-开发进阶Django-form组件中model form组件

Django-form组件中过滤当前用户信息