数据模型依赖关系,我可以简化这些对象吗



本质上,我有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')

然后,如果您喜欢的话,您可以使依赖关系成为模型ABC上的反向泛型关系:

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)

你的类BCA的字段加上一个额外的字段,所以我们可以将其重写为

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)

现在可以将ABC对象中的任何一个设置为dependentTodependents。如果您只需要依赖项中的主对象,则类型为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的值(表示类型为BC的对象)。然后,您的依赖类与前面的示例相同,但您不需要处理这些向后关系来测试真正的对象类型。

如果你真的需要在BC对象之间伪装,你可以这样写你的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不是nullobj_type是A或类似情况。

如果您需要此解决方案,请告诉我。

最新更新