【问题标题】:Get the FK attributes of a model , if a model is passed如果传递了模型,则获取模型的 FK 属性
【发布时间】:2018-09-01 09:52:31
【问题描述】:

我有以下型号:

class Comp(models.Model):
      ....
       is_active = models.BooleanField(default=False)

class Item(models.Model):

      comp = models.ForeignKey(Comp, blank=True, null=True, related_name='items', on_delete=models.CASCADE)
        romp = models.ForeignKey(Romp, blank=True, null=True, related_name='items', on_delete=models.CASCADE)
        is_active = models.BooleanField(default=False)

我想编写一个通用模型clean 方法来检查模型的non Null 外键,如果他们的is_active=True

我想在多个模型上继承这个方法(使用抽象模型)

在下面的代码中,我通过 FK 的一般列表检查每个模型属性

def clean(self, *args, **kwargs):
    ....
            for attr in FK_LIST:
                if hasattr(self, attr):
                    fk_obj = getattr(self, attr)
                    if not fk_obj.active:
                        raise ValidationError({'is_active': 'The {} {} needs to be active first'
                                              .format(type(fk_obj).__name__, fk_obj.name)})

我的代码有 2 个问题:

  1. 我有两个手动维护一个 FK 名称列表
  2. 我需要循环遍历所有属性,而不是只检查 FK
  3. 我不希望有一个隐式的 FK_list 来签入,而是有一个排除列表(易于维护): 检查模型上所有非 NULL 或 Exclude_list 中的 FK

【问题讨论】:

  • 只有外键?我也假设OneToOneFields? ManyToManyFields 或 OneToMany 等其他关系呢?
  • 只是FK,OnetoOne,我喜欢层次关系,所以如果父母不活动,我只是不想激活孩子
  • @use3541631:如果你定义了OneToOneField,django 会自动在引用的模型中创建一个反向字段。

标签: django django-models


【解决方案1】:

您可以使用self._meta.fields 获取列列表。这将生成一个包含字段的元组,值是列定义。

我们可以迭代此列,并检查类型是否为ForeignKey。在这种情况下,我们将执行检查:

def clean(self, *args, **kwargs):
    # ...
    for field in self._meta.fields():
        if isinstance(field, ForeignKey):
            fk_obj = getattr(self, field.name)
            if not fk_obj.active:
                raise ValidationError({'is_active': 'The {} {} needs to be active first'
                                              .format(type(fk_obj).__name__, fk_obj.name)})

或者我们可以过滤掉非继承的:

def clean(self, *args, **kwargs):
    # ...
    for field in self._meta.get_fields(include_parents=False):
        if isinstance(field, ForeignKey):
            fk_obj = getattr(self, field.name)
            if not fk_obj.active:
                raise ValidationError({'is_active': 'The {} {} needs to be active first'
                                              .format(type(fk_obj).__name__, fk_obj.name)})

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-05-04
  • 1970-01-01
  • 2019-12-23
  • 2014-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-10
相关资源
最近更新 更多