django,manytomany通过具有通用外键的表?

时间:2013-12-12 05:48:11

标签: django many-to-many

假设ModelA和(ModelB1,ModelB2但它们没有共同的祖先)有很多关系。

现在我有一个through模型ModelAtoB。

class ModelAToB(Model):
    model_a = models.ForeignKey(ModelA)

    content_type=models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    model_b = generic.GenericForeignKey('content_type', 'object_id')

我看到在Django doc中使用了ManyToManyField,我怎样才能在我的情况下使用它?

class ModelA(Model):
  pass

class ModelB(Model): # hum.. there's no ModelB which is a common ancestor of ModelB1, ModelB2
  model_a_list = models.ManyToManyField(ModelA, through='ModelAtoB')

1 个答案:

答案 0 :(得分:0)

你不能在你的情况下使用ManyToManyField,但你的直通模型(ModelAToB)足以存储关系。

如果您想要查询给定ModelAs的所有相关ModelBs模型,您可以这样做:

related_b = ModelAToB.objects.filter(model_a=a).prefetch_related('model_b')
b_instances = [rel.model_b for rel in related_b]

如果您希望所有相关的ModelAs到达给定的ModelB,则可以这样做:

from django.contrib.contenttypes.models import ContentType

model_b_ct = ContentType.objects.get_for_model(b)

related_a = ModelAToB.objects.filter(object_id=b.id, content_type=model_b_ct)
a_instance = [rel.model_a for rel in related_a]

制作模型方法可能是一个方便的调整。

class ModelB(Model)::

    def model_a_list(self):
        return ModelA.objects.filter(
                modelatob__content_type__app_label=self._meta.app_label, 
                modelatob__content_type__model=self._meta.module_name, 
                modelatob__object_id=self.id
        )

这会返回一个查询集,因此您仍然可以执行.count(),.。filter()等操作。