Django:重用表单字段而不继承?

2023-12-31

如果我有两个基于不同基类(例如 Form 和 ModelForm)的表单,但我想在这两个表单中使用一些字段,我可以以 DRY 方式重用它们吗?

考虑以下场景:

class AfricanSwallowForm(forms.ModelForm):
    airspeed_velocity = forms.IntegerField(some_important_details_here)
    is_migratory = forms.BooleanField(more_important_details)

    class Meta:
        model = AfricanBird

class EuropeanSwallowForm(forms.Form):
    airspeed_velocity = forms.IntegerField(some_important_details_here)
    is_migratory = forms.BooleanField(more_important_details)

....有没有办法可以重用airspeed_velocity 和is_migatory 字段?想象一下我有几十个此类表格。如果我一遍又一遍地写这些代码,代码将会变得很糟糕。

(假设,出于这个问题的目的,我不能或不会将 airspeed_velocity 和 is_migatory 转换为模型 AfricaBird 的字段。)


你可以使用多重继承又名mixins,分解出 Form 和 ModelForm 中使用的字段。

class SwallowFormFields:
    airspeed_velocity = forms.IntegerField( ... )
    is_migratory = forms.BooleanField( ... )

class AfricanSwallowForm(forms.ModelForm, SwallowFormFields):
    class Meta:
        model = AfricanBird

class EuropeanSwallowForm(forms.Form, SwallowFormFields):
    pass

UPDATE:

由于这不适用于 Django 元编程,因此您需要创建一个自定义__init__构造函数将继承的字段添加到对象的字段列表中,或者您可以在类定义中显式添加引用:

class SwallowFormFields:
    airspeed_velocity = forms.IntegerField()
    is_migratory = forms.BooleanField()

class AfricanSwallowForm(forms.ModelForm):
    airspeed_velocity = SwallowFormFields.airspeed_velocity
    is_migratory = SwallowFormFields.is_migratory
    class Meta:
        model = AfricanSwallow

class EuropeanSwallowForm(forms.Form):
    airspeed_velocity = SwallowFormFields.airspeed_velocity
    is_migratory = SwallowFormFields.is_migratory

UPDATE:

当然,您不必将共享字段嵌套到类中 - 您也可以简单地将它们定义为全局变量......

airspeed_velocity = forms.IntegerField()
is_migratory = forms.BooleanField()

class AfricanSwallowForm(forms.ModelForm):
    airspeed_velocity = airspeed_velocity
    is_migratory = is_migratory
    class Meta:
        model = AfricanSwallow

class EuropeanSwallowForm(forms.Form):
    airspeed_velocity = airspeed_velocity
    is_migratory = is_migratory

UPDATE:

好吧,如果你真的想最大限度地干燥,你必须选择元类.

所以你可以这样做:

from django.forms.models import ModelForm, ModelFormMetaclass
from django.forms.forms import get_declared_fields, DeclarativeFieldsMetaclass
from django.utils.copycompat import deepcopy

class MixinFormMetaclass(ModelFormMetaclass, DeclarativeFieldsMetaclass):
    def __new__(cls, name, bases, attrs):

        # default __init__ that calls all base classes
        def init_all(self, *args, **kwargs):
            for base in bases:
                super(base, self).__init__(*args, **kwargs)
        attrs.setdefault('__init__', init_all)

        # collect declared fields
        attrs['declared_fields'] = get_declared_fields(bases, attrs, False)

        # create the class
        new_cls = super(MixinFormMetaclass, cls).__new__(cls, name, bases, attrs)
        return new_cls

class MixinForm(object):
    __metaclass__ = MixinFormMetaclass
    def __init__(self, *args, **kwargs):
        self.fields = deepcopy(self.declared_fields)

您现在可以从 MixinForm 派生表单字段集合,如下所示:

class SwallowFormFields(MixinForm):
    airspeed_velocity = forms.IntegerField()
    is_migratory = forms.BooleanField()

class MoreFormFields(MixinForm):
    is_endangered = forms.BooleanField()

然后将它们添加到基类列表中,如下所示:

class EuropeanSwallowForm(forms.Form, SwallowFormFields, MoreFormFields):
    pass

class AfricanSwallowForm(forms.ModelForm, SwallowFormFields):
    class Meta:
        model = AfricanSwallow

那么它有什么作用呢?

  • 元类收集 MixinForm 中声明的所有字段
  • 然后它添加自定义__init__构造函数,以确保__init__MixinForm 的方法被神奇地调用。 (否则你必须显式调用它。)
  • MixinForm.__init__复制字段属性中声明的字段

请注意,我既不是 Python 专家,也不是 django 开发人员,并且元类是危险的。因此,如果您遇到奇怪的行为,最好坚持使用上面更详细的方法:)

祝你好运!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django:重用表单字段而不继承? 的相关文章

随机推荐

  • 如何使用 React.js 在 Botframework v4 聊天应用程序中执行发送“打字指示器”?

    我正在使用 botframework v4 构建一个聊天应用程序 以 React js 作为前端 以 net core 作为后端来生成令牌 我想使用 React 在我的聊天中实现 Typing 指示器 尝试使用 window WebChat
  • Ubuntu 上的 rpy2 安装

    我对 Linux 还很陌生 在安装 Rpy2 时遇到了一些严重的问题 我通过突触包管理器安装了旧版本的 Rpy2 但我需要更新版本并将其删除 如 Rpy2 文档中所述 Rpy2 目录中的所有文件 我下载了tar gz 来自 SourceFo
  • 如何使用 Timer 创建时钟?

    我正在尝试创建一个七段显示 它使用计时器以及 ActionListener 和 actionPerformed 自动移动 我认为如果我使用 for if 语句 它会自动从 0 循环到 2 并为每个数字段设置背景颜色 但是 当我显示它时 它停
  • HtmlAgility:没有出现任何内容(C#,UWP)

    我尝试使用 htmlagilitypack 来解析表格 完成后我意识到我忘记证明 htmlagility 部分是否有效 很明显它不起作用 我也不知道我错过了什么 我在哪里做错了 因为我是初学者 所以请不要对我太严厉 public parti
  • 获取资源错误

    每次我在主要活动中调用 getResources 时 都会导致错误并且应用程序被迫退出 如果我调用 getApplicationContext getResources 甚至在 Eclips 中的全新项目中也会发生这种情况 在通话之前我需要
  • 使用 CSS 替换 ul 项目符号点样式

    我想替换 ul 列表的列表样式类型属性 以便外部是一个圆盘 然后一个内部 ul 列表是一个圆 再一个内部是一个圆盘 依此类推 本质上 我想要的是这样的 ul li Lorem ipsum li li ul li Lorem ipsum li
  • 如何将匿名类型转换为已知类型

    我有一个匿名类型变量 该变量是从另一个函数获取的 我们无法更改它 var a property1 abc property2 def 我有一堂课 class Myclass string property1 string property2
  • 根据用户输入设置选中的复选框

    我有这些 HTML 元素 div div
  • 将 sql_variant 转换为 varchar 形式提供的 data_type

    我有一个如下的sql表 Types table Name varchar 50 Type varchar 50 Car varchar 50 Apples int 我正在使用另一个表来存储值 例如 Apples table V
  • 如何在 iBatis 中获得排序结果?

    我有一个表 mgr employee 有 2 列 managerName teamEmployee 虽然我在 sql 中进行了排序 但我在 java 中得到了未排序的 resultMap 如何获得排序后的地图 为什么 iBatis 会混淆
  • Kubernetes:从远程浏览器访问仪表板

    我有一个小型 Kubernetes 集群 主要是 这本教程 https www profiq com kubernetes cluster setup using virtual machines 因此 我在 Virtual Box Cen
  • Highcharts - 休息 1 小时

    我似乎无法弄清楚为什么 x 轴上的时间总是晚一个小时 我知道它与这条线有关 但我不知道将其更改为什么 date Date parse line 0 UTC 我当前的时区是伦敦 我有这个文件 index php
  • 创建跨 Maven 测试阶段工作的临时数据库?

    我加入了一个项目 该项目有很多带有 SQL 语句的文件 用于创建用于集成测试的数据库 我想知道如何使用这些文件来创建用于单元测试的数据库 使用java和maven 我可以为每个单元测试创 建一个 HSQL 内存数据库 甚至可以使用 spri
  • 如何使用 SimpleHtmlDom 在 HTML 的 head 标签之间插入链接标签

    我试图通过使用来操作 HTML 代码simplehtmldom sourceforge net http simplehtmldom sourceforge net 这是我到目前为止所得到的 我可以创建一个新文件或将索引 html to 索
  • 所有 ajax 请求完成后执行代码

    我有一个相当复杂的搜索 它利用多个ajax调用 流程如下 user performs search on button click ajax request is made to php page which returns json da
  • WPF&MVVM:库 System.Windows.Interactivity 不再可用?

    我需要添加System Windows Interactivity dll图书馆通过Reference Manager In Visual Studio 2017 我没找到 所有从以下位置开始的搜索结果System Windows如下面的屏
  • 为什么“git add *”不会添加“git status”表示未暂存的文件?

    当我打字时 git add 它的表现就好像没有添加文件 但当我这样做时 git status 它显示未暂存的文件 我可以通过手动输入名称来暂存它们 如图所示 但在相同情况下这需要相当长的时间 我的问题是 在这种情况下 为什么我不能只输入 g
  • 在java中处理n个if-else if的更好方法

    我想知道是否有更好的方法来处理n no Java 中的 if else if 块 我有一种情况 我需要根据 n 打印不同的值 if else if conditions 块如 if p 1 q r System out println Co
  • angular2,打字稿对等无效,无法导入模块

    我有两个问题 可能它们相互依赖 我无法要求 导入 电子邮件受保护 cdn cgi l email protection 打字稿可以工作 但我看到错误 通过命令 npm list email protected cdn cgi l email
  • Django:重用表单字段而不继承?

    如果我有两个基于不同基类 例如 Form 和 ModelForm 的表单 但我想在这两个表单中使用一些字段 我可以以 DRY 方式重用它们吗 考虑以下场景 class AfricanSwallowForm forms ModelForm a