django中使用基于BaseForm统一对BootStrap样式优化组件

文章目录

使用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.Formforms.ModelForm),子类可以定义自己的字段。这些字段定义是通过 Django 的 DeclarativeFieldsMetaclass 元类在类定义时自动收集的。

这里是继承和字段收集过程的简化示例:
  1. DeclarativeFieldsMetaclass - 这是一个元类,负责在类定义时收集所有字段声明,并将它们存储在 declared_fields 属性中。

  2. Form (继承自 BaseForm) - 这是一个具体的表单类,使用 DeclarativeFieldsMetaclass 作为其元类。当你在 Form 类中定义字段时,这些字段被 DeclarativeFieldsMetaclass 收集,并最终存储在 base_fields 属性中。

  3. BaseForm - 这个类提供了表单的基础架构,包括 __init__ 方法,该方法创建 self.fields 的深拷贝。由于 BaseForm 是一个基类,它不定义 base_fields,而是由其子类在元类的辅助下定义。

所以,当你创建一个表单实例时,例如 MyForm(),Django 首先使用 DeclarativeFieldsMetaclass 来处理类定义,收集所有字段声明,并设置 base_fields。然后,当你实例化 MyForm 时,BaseForm__init__ 方法被调用,它深拷贝 base_fieldsself.fields,为表单实例创建一个字段的独立副本。

这是 BaseForm__init__ 方法的一个片段,展示了 self.fields 是如何从 base_fields 创建的:

python 复制代码
class 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一起进步吧!!!

相关推荐
boooo_hhh2 小时前
第40周——GAN入门
人工智能·python·机器学习
ChaoQiezi2 小时前
Python:如何在Pycharm中显示geemap地图?
python·gee
小白学大数据2 小时前
1688商品数据抓取:Python爬虫+动态页面解析
爬虫·python·okhttp
华科云商xiao徐3 小时前
突破Python性能墙:关键模块C++化的爬虫优化指南
c++·爬虫·python
躲在云朵里`3 小时前
常用Linux指令:Java/MySQL/Tomcat/Redis/Nginx运维指南
开发语言·python
小白狮ww4 小时前
蛋白质设计新高度,RFdiffusion 实现从零设计高亲和力蛋白质
人工智能·python·开源
星火飞码iFlyCode4 小时前
真实案例 | 如何用iFlyCode开发Webpack插件?
java·python·编辑器
三只熊猫4 小时前
一文打通 AI 知识脉络:大语言模型等关键内容详解
人工智能·python
Kyln.Wu5 小时前
【python实用小脚本-187】Python一键批量改PDF文字:拖进来秒出新文件——再也不用Acrobat来回导
python·pdf·c#
xnglan5 小时前
蓝桥杯手算题和杂题简易做法
数据结构·数据库·c++·python·算法·职场和发展·蓝桥杯