【问题标题】:Reuse Django field definitions in other models在其他模型中重用 Django 字段定义
【发布时间】:2021-11-26 11:41:49
【问题描述】:

我在不同的模型中有几个字段。例如

class A(models.Model):
    field_1 = models.CharField(max_length=5, blank=False)
    field_2 = models.CharField(max_length=100, blank=False)
    field_3 = models.CharField(max_length=200, blank=False)

class B(models.Model):
    field_4 = models.CharField(max_length=5, blank=False)
    field_5 = models.CharField(max_length=100, blank=False)
    field_6 = models.CharField(max_length=200, blank=False)

除了这些课程之外,我还想创建一个领导班。此类包含将来可能复制到其他模型中的数据。因此,数据约束是相同的,但由于这是可选数据,因此可能会丢失一些数据。

我想使用 DRY,但我也想更新空白字段。有关如何使用这些原始类中的确切字段定义的任何提示?

class Lead(models.Model):
    field_1 = A.field_1  # but with updated blank field
    field_3 = B.field_3  # but with updated blank field

我考虑过类依赖,但实际上我正在使用来自 5 个类的字段,我担心如果领导类依赖于这些字段,它们会变得难以阅读。

【问题讨论】:

  • 您是否尝试过创建一个抽象类并将其用于其他人?
  • @amadou-sow,是的,我按照上一段中提到的那样做了。但是我认为这可能会变得难以阅读。最重要的是,在这种情况下,将空白更改为 True/False 更加困难。
  • 阅读更多 Django 文档后,我开始相信这是不可能的。 “在正常的 Python 类继承中,允许子类覆盖父类的任何属性。在 Django 中,模型字段通常不允许这样做。” - docs.djangoproject.com/en/dev/topics/db/models/…

标签: python django django-models


【解决方案1】:

Django ORM

由于 Django 在 Python 之上添加了一个层,因此类依赖的工作方式有所不同。仅引用另一个非抽象类中的字段定义并覆盖字段是not allowed,因为它会破坏数据库或引入令人讨厌的错误。

解决方案

不要引用函数,而是使用内置函数clone()复制它。

# Create a new function to gather the field definition from another model
def get_field_from_model(model, field):
    return model._meta.get_field(field)


def modify_field(base_model, base_field, **kwargs):
    field = get_field_from_model(base_model, base_field)
    field_copy = field.clone()
    field_copy.__dict__.update(kwargs)
    return field_copy

官方 _meta 是一个隐藏类,但它被认为是稳定的并且是 official API。但是,如果这种情况发生变化,我会将它放在一个单独的函数中以便快速访问。这种方法基于更详细的答案here(解决方案类似,原始问题侧重于从变量中复制字段而不是在类定义中)。

实施

现在这个函数可以在类定义中使用了。它也在迁移步骤中被识别,并将基于引用的字段创建新字段。

class Lead(models.Model):
    field_1 = modify_field(A, 'field_1', blank = True)
    field_3 = modify_field(B, 'field_3', blank = True)

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 2020-11-29
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多