【问题标题】:Django - Foreign key from abstract base class [duplicate]Django - 来自抽象基类的外键[重复]
【发布时间】:2023-04-11 10:55:05
【问题描述】:

可能重复:
Polymorphism in Django models

我有一个约束抽象基础模型,它有一个组的外键。几个模型从 Constraint 继承,以各种不同的方式运行。这是我所拥有的(非常简化的)版本:

class Constraint(models.Model):
    group = models.ForeignKey(Group)

    def get_constraint_type(self):
        return 'Base'

    class meta:
        abstract = True

class UserConstraint(Constraint):
    user = models.ForeignKey(User)

    def get_constraint_type(self):
        return 'User'

class ProjectConstraint(Constraint):
    project = models.ForeignKey(Project)

    def get_constraint_type(self):
        return 'Project'

给定一个组,我需要能够提出一个指向它的约束模型实例列表。

例如如果我这样做了

group = ...
constraints = group.constraint_set.all()
for c in constraints:
    print c.get_constrait_type()

现在,它会打印很多次“Base”,而不是“User”、“Project”、“User”等。

一个非常老套的解决方案是在基类中实现这样的函数:

def get_child(self):
    try:
        return self.usercontraint
    except UserConstraint.DoesNotExist:
        pass
    try:
        return self.projectcontraint
    except ProjectConstraint.DoesNotExist:
        pass
    # etc...

但这看起来真的很糟糕。有没有更好的解决方案?

【问题讨论】:

标签: python django inheritance model


【解决方案1】:

所以,您的意思是您有 Group 模型的实例,并且您希望有与 UserConstraint 或 ProjectConstraint 相关的查询集?

有解决方案可以在 ForeignKey 字段中使用适当的related_name 参数来实现这一点。详情请见docs

我认为你应该像这样定义约束模型:

class Constraint(models.Model):
    group = models.ForeignKey(Group, related_name="%(class)s_set")

    def get_constraint_type(self):
        return 'Base'

    class Meta:
        abstract = True

并像这样使用它:

user_constraints = group.userconstraint_set.all()
project_constraints = group.projectconstraint_set.all()

编辑:

我已将 related_name"%(class)s" 更改为 "%(class)s_set"。以前的值不起作用,我不知道为什么。

【讨论】:

  • 我希望能够一次查询所有约束。例如group.() 应该返回用户和项目约束。从那里开始,我将在每个子类中拥有相同的函数名称,因此无论它位于哪个子类中,调用 c.get_constraint_type() 都将起作用。
  • 在后台必须有两个查询到数据库,所以很难用一个查询集来完成。如果您有一堆子类,也许不错的选择是自省约束以使用Constraint.__subclasses__() 方法获取子类并生成要加入的查询集列表。
  • 如果你想要related_name的复数,你需要在末尾添加一个额外的s:“%(class)ss”。
猜你喜欢
  • 1970-01-01
  • 2018-07-11
  • 2010-09-26
  • 2016-04-15
  • 2021-05-29
  • 2016-06-10
  • 2016-08-18
  • 1970-01-01
  • 2011-11-23
相关资源
最近更新 更多