本质上,我有6个对象模型,其中3个用于常规对象,3个用于这些对象的依赖关系。单独地,这些对象可以依赖于3个规则对象中每一个的一个或多个实例。
我的问题:这是最佳实践吗?我本质上希望能够在需要时向常规对象添加一个新的依赖项。例如:
a = A.objects.get(id=1)
adependency = ADependencies.objects.get(dependentTo=a)
然后,我将拥有一个具有a
所有依赖项的对象。
或者,我确实想了一种方法将3个依赖对象合并为一个;然而,我不确定这是否是一种好的做法。
class Dependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = CharField(max_length=16)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
在这个场景中,我不使用ForeignKey来映射dependentTo对象。相反,我会使用对象id来拉取对象——这让我可以是类无关的;然而,这将需要贯穿3个常规对象的唯一id。
a = A.objects.get(id=1)
adependency = ADependencies.objects.get(dependentTo=a.id)
还有一个想法是否可能仍然使用ForeignKey,而是传入一个带有类名的字符串?
class Dependencies(models.Model):
id = models.CharField(max_length=16)
type = models.CharField(max_length=16)
dependentTo = ForeignKey(type)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
对象模型:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
class B(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A)
class C(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
b = models.ForeignKey(B)
class ADependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(A)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
class BDependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(B)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
class CDependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(B)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
谢谢!
这可以做得简单得多。定义Dependency
模型而不是Dependencies
模型。您将需要内容类型django贡献:
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Dependency(models.Model):
dependent_contenttype = models.ForeignKey(ContentType)
dependent_id = models.PositiveIntegerField()
dependent = GenericForeignKey('dependent_contenttype', 'dependent_id')
prerequisite_contenttype = models.ForeignKey(ContentType)
prerequisite_id = models.PositiveIntegerField()
prerequisite = GenericForeignKey('prerequisite_contenttype',
'prerequisite_id')
然后,如果您喜欢的话,您可以使依赖关系成为模型A
、B
和C
上的反向泛型关系:
class A:
# ...
dependencies = GenericRelation(
Dependency,
content_type_field='dependent_contenttype',
object_id_field='dependent_id')
我认为继承可以大大简化数据结构。
让我们让模型A
保持原样:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
你的类B
和C
有A
的字段加上一个额外的字段,所以我们可以将其重写为
class B(A):
a = models.ForeignKey(A)
class C(A):
b = models.ForeignKey(B)
现在,由于我们有一个基类,我们只需要一个依赖类:
class ADependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(A)
dependents = models.ManyToManyField(A)
现在可以将A
、B
和C
对象中的任何一个设置为dependentTo
和dependents
。如果您只需要依赖项中的主对象,则类型为A
的对象将具有属性b
、属性c
,或者不具有它们。您也可以查询这些属性:
ADependencies.objects.filter(dependentTo__b__isnull=False)
这种结构更具可扩展性,更易于维护,因为如果您需要再添加一个模型,您只需要为它编写唯一的代码,而不必处理依赖类。
简化模型的另一种方法是只有一个模型:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A, null=True)
这样,您只有模型A
,可以将字段a
留空(表示它只是一个简单的A
实例)或设置a
的值(表示类型为B
或C
的对象)。然后,您的依赖类与前面的示例相同,但您不需要处理这些向后关系来测试真正的对象类型。
如果你真的需要在B
和C
对象之间伪装,你可以这样写你的A
类:
class A(models.Model):
A = 0
B = 1
C = 2
TYPE_CHOICES = (
(A, "A"),
(B, "B"),
(C, "C")
)
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A, null=True)
obj_type = models.IntegerField(choices=TYPE_CHOICES)
这样,您就只有一个模型类和一个依赖类,并且可以通过检查obj_type
来判断对象的类型。此外,您还应该执行一些检查,以防止出现a
不是null
、obj_type
是A或类似情况。
如果您需要此解决方案,请告诉我。