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

时间:2015-04-24 23:25:15

标签: python django

基本上我有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)

谢谢!

2 个答案:

答案 0 :(得分:1)

这可以做得更简单。定义Dependency模型而不是Dependencies模型。您将需要contenttypes 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')

答案 1 :(得分:0)

我认为继承可能会大大简化您的数据结构。

让我们按原样保留模型$var1 = 01002992456; echo "$var1";

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) AB个对象设置为CdependentTo。如果您只需要依赖项中的主对象,则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的值(它将表示aB类型的对象。然后您的依赖类与前面的示例相同,但您不需要处理那些向后关系来测试真实对象类型。

如果你真的需要在CB对象之间进行区分,你可以像这样编写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不是anull为A且类似的情况。

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