Tal*_*Tal 9 django orm django-models
我们目前正在运行以下配置以避免其他问题.
所以对于这个问题:让我们假设这是必须的,我们不能改变模型部分.
一开始我们有以下模型:
class A(Model):
b = ForeignKey(B)
... set of fields ...
class B(Model):
...
Run Code Online (Sandbox Code Playgroud)
然后我们添加了这样的东西:
class AVer2(Model):
b = ForeignKey(B)
... ANOTHER set of fields ...
Run Code Online (Sandbox Code Playgroud)
假设一个对象type B只能由两个A或AVer2 两个引用:
有没有办法在B上运行查询,它将在运行时返回查询结果中引用它的正确对象类型(并且查询中包含两种类型)?
您可以假设类型B的对象包含有关谁引用它的信息.
我试图避免代价高昂的整个系统代码更改.
编辑:显然,我的问题不明确.所以我会尝试更好地解释它.我得到的答案很棒,但显然我错过了我的问题中的一个关键点,所以在这里.假设我有上面的模型B,我得到一些对象:
b_filter = B.objects.filter(some_of_them_have_this_true=True)
Run Code Online (Sandbox Code Playgroud)
现在,我希望得到A和AVer2中的一个字段,其中一个过滤器放入一个值列表中.所以例如,我想得到一个名为"MyVal"的字段(A和AVer2都有它)我不关心实际类型是什么.所以我想写一些像:
b_filter.values(['a__myval', 'aver2__myval'])
Run Code Online (Sandbox Code Playgroud)
并得到类似以下内容的回报:[{'myval':}]相反,我现在得到[{'a__myval':,'aver2__myval':无}]
我希望它更清楚.
谢谢!
我不确定你想在查询集中得到什么。
我假设您想要一组“正确的对象类型”,“其中包含两种类型”,所以实际上您想要一组相关的类类型(例如[<class 'main.models.A'>, <class 'main.models.A2'>])。如果情况并非如此,我可以在评论中提供更多具体细节后更改答案。
这是“类列表”的解决方案,您可以使用它来获得您想要的东西。
# Our custom QuerySet that with function that returns list of classes related to given B objects
class CustomQuerySet(models.QuerySet):
def get_types(self, *args, **kwargs):
all_queryset = self.all()
return [b.get_a() for b in all_queryset]
# Our custom manager - we make sure we get CustomQuerySet, not QuerySet
class TypesManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return CustomQuerySet(self.model)
class B(models.Model):
# some fields
# Managers
objects = models.Manager()
a_types_objects = TypesManager()
# Get proper A "type"
def get_a(self):
if self.a_set.all() and self.a2_set.all():
raise Exception('B object is related to A and A2 at the same time!')
elif self.a_set.all():
return A
elif self.a2_set.all():
return A2
return None
class A(models.Model):
b = models.ForeignKey(
B
)
class A2(models.Model):
b = models.ForeignKey(
B
)
Run Code Online (Sandbox Code Playgroud)
现在你可以像这样使用它:
>>> from main.models import *
>>> B.a_types_objects.all()
<CustomQuerySet [<B: B object>, <B: B object>]>
>>> B.a_types_objects.all().get_types()
[<class 'main.models.A'>, <class 'main.models.A2'>]
>>> B.a_types_objects.filter(id=1)
<CustomQuerySet [<B: B object>]>
>>> B.a_types_objects.filter(id=1).get_types()
[<class 'main.models.A'>]
Run Code Online (Sandbox Code Playgroud)
使用a_types_objects方法与普通方法类似objects,但它返回 CustomQuerySet,它具有返回类列表的额外函数。
编辑:
如果您担心更改很多B.objects.(...)内容,B.a_types_objects.(...)您可以将主管理器设置为 TypesManager,如下所示:
class B(models.Model):
# some fields
# Override manager
objects = TypesManager()
Run Code Online (Sandbox Code Playgroud)
其余代码将保持不变,但从现在开始,您将使用 CustomQuerySet 而不是 QuerySet - 仍然没有任何真正的变化。
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |