我们目前正在使用以下配置运行,以避免其他问题。
因此,对于这个问题:让我们假设这是必须的,并且我们不能更改Models部分。
最初,我们有以下模型:
class A(Model):
b = ForeignKey(B)
... set of fields ...
class B(Model):
...
然后,我们添加了以下内容:
class AVer2(Model):
b = ForeignKey(B)
... ANOTHER set of fields ...
假设
type B
的对象只能由A
或AVer2
引用,但不能同时由引用:有没有一种方法可以在B上运行查询,该查询将在运行时在查询结果中返回引用该对象的正确对象类型(并且查询中同时包含这两种类型)?
您可以假定类型B的对象包含有关谁在引用它的信息。
为此,我试图避免进行昂贵的整个系统代码更改。
编辑:
显然,我的问题不清楚。因此,我将尝试更好地解释它。我得到的答案很好,但是显然我错过了问题的关键点,所以就在这里。假设我有上面的模型B,并且得到了一些对象:
b_filter = B.objects.filter(some_of_them_have_this_true=True)
现在,我想获得一个在A和AVer2中都包含一个字段的字段,其中一个过滤器进入一个值列表。因此,例如,我想获取一个名为“MyVal”的字段(A和AVer2都有),我不在乎实际的类型是什么。所以我想写一些类似的东西:
b_filter.values(['a__myval', 'aver2__myval'])
并得到如下所示的信息:[{'myval':}]
相反,我目前得到了[{'a__myval':,'aver2__myval':None}]
我希望情况更清楚。
谢谢!
最佳答案
简短的回答:您无法满足您的确切需求。
长答案:当我读到您的问题时,我想到的第一件事是Content Types,Generic Foreign Keys and Generic Relations
无论您将使用“普通”外键还是“通用外键”(与“通用关系”结合使用),您的B
实例都将同时具有A field
和AVer2 field
,而这种自然的事物将使生活更轻松,并使您的目标变得更容易(B实例具有一个可能是A或Avr2)无法访问。在这里,您还应该覆盖B model save method
,以强制其仅将A字段和Avr2设置为None或将A设置为None并将Avr2使用。而且,如果这样做,请不要忘记将null=True, blank=True
添加到A和Avr2外键字段。
另一方面,架构的相反之处使您可以实现目标:B
模型引用A
和Avr2
,这意味着B
模型对generic foreign key
和A
都具有一个Avr2
,如下所示:(此代码在Django 1.8中,对于Django 1.9或更高版本,GenericRelation的导入,GenericForeignKey已更改)
from django.db import models
from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class B(models.Model):
# Some of your fields here...
content_type = models.ForeignKey(ContentType, null=True, blank=True)
object_id = models.PositiveIntegerField(null=True, blank=True)
# Generic relational field will be associed to diffrent models like A or Avr2
content_object = GenericForeignKey('content_type', 'object_id')
class A(models.Model):
# Some of your fields here...
the_common_field = models.BooleanField()
bbb = GenericRelation(B, related_query_name="a") # since it is a foreign key, this may be one or many objects refernced (One-To-Many)
class Avr2(models.Model):
# Some of your fields here...
the_common_field = models.BooleanField()
bbb = GenericRelation(B, related_query_name="avr2") # since it is a foreign key, this may be one or many objects refernced (One-To-Many)
现在,A和Avr2都具有作为B实例的“bbb”字段。
a = A(some fields initializations)
a.save()
b = B(some fields initializations)
b.save()
a.bbb = [b]
a.save()
现在您可以执行
a.bbb
并获得B
实例然后像这样从
A
中获取Avr2
或b
:b.content_object # which will return an `A object` or an `Avr2 object`
现在让我们回到您的目标:
是:像这样:
B.objects.get(id=1).content_type # will return A or Avr2
b_filter = B.objects.filter(some_of_them_have_this_true=True)
:从django.db.models导入Q
过滤器= Q(a__common_field = True)| Q(avr2__common_field = True)
B.objects.filter(filter)
[{'a__myval': , 'aver2__myval': None}]
提供两个字段值,所以获取values
是100%正常的。解决此问题的一种方法是获取两个干净的查询,然后将它们链接在一起,如下所示:从itertools进口链
c1 = B.objects.filter(content_type__model ='a')。values('a__common_field')
c2 = B.objects.filter(content_type__model ='avr2')。values('avr2__common_field')
result_list = list(chain(c1, c2))
请注意,当我们向通用关系添加
related_query_name
时,可以从a
实例访问avr2
和B
,这不是默认情况。和瞧!我希望这有帮助 !