文章目录
使用Form或者ModelForm时可以统一对BootStrap样式优化
预备知识
mro
super().__init__()
:不是执行父类中的__init__
方法,而是按照类的MRO(类的继承关系,Method Resolution Order)顺序,从下往上执行,可以通过==类名.mro()
或者类名.__mro__
==得到该类的继承关系。
Form/ModelForm继承和字段收集过程
在 Django 的
BaseForm
类中,base_fields
属性确实是在__init__
方法中被深拷贝到self.fields
的,但在深拷贝之前,base_fields
属性实际上已经通过继承链被设置好了。
BaseForm
本身不直接定义任何字段,但它作为一个基类,可以被子类继承。当你创建一个继承自BaseForm
的子类时(例如forms.Form
或forms.ModelForm
),子类可以定义自己的字段。这些字段定义是通过 Django 的DeclarativeFieldsMetaclass
元类在类定义时自动收集的。这里是继承和字段收集过程的简化示例:
DeclarativeFieldsMetaclass - 这是一个元类,负责在类定义时收集所有字段声明,并将它们存储在
declared_fields
属性中。Form (继承自 BaseForm) - 这是一个具体的表单类,使用
DeclarativeFieldsMetaclass
作为其元类。当你在Form
类中定义字段时,这些字段被DeclarativeFieldsMetaclass
收集,并最终存储在base_fields
属性中。BaseForm - 这个类提供了表单的基础架构,包括
__init__
方法,该方法创建self.fields
的深拷贝。由于BaseForm
是一个基类,它不定义base_fields
,而是由其子类在元类的辅助下定义。所以,当你创建一个表单实例时,例如
MyForm()
,Django 首先使用DeclarativeFieldsMetaclass
来处理类定义,收集所有字段声明,并设置base_fields
。然后,当你实例化MyForm
时,BaseForm
的__init__
方法被调用,它深拷贝base_fields
到self.fields
,为表单实例创建一个字段的独立副本。这是
BaseForm
中__init__
方法的一个片段,展示了self.fields
是如何从base_fields
创建的:
pythonclass BaseForm: # ... def __init__(self, data=None, files=None, *args, **kwargs): # ... 省略了其他初始化代码 ... # Instances should always modify self.fields; they should not modify # self.base_fields. self.fields = copy.deepcopy(self.base_fields) # ... 省略了其他初始化代码 ...
在这个示例中,
self.base_fields
是在类定义时通过元类设置的,然后在实例化时被深拷贝到self.fields
。这样,每个表单实例都有自己的字段副本,而不会相互影响。
多继承来简化对统一样式的处理
python
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)
使用
python
from django.shortcuts import render, redirect
from web import models
from django import forms
from django.urls import reverse
from ... import BootStrapForm
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']
levelmodelform = LevelModelForm() # ['BootStrapForm','forms.ModelForm','BaseModelForm','BaseForm']
levelform = LevelForm() # ['BootStrapForm','BaseModelForm','BaseForm']
若有错误与不足请指出,关注DPT一起进步吧!!!