wim*_*wim 11 python django postgresql generic-relations generic-foreign-key
我正在使用Django v1.9.4和PostgreSQL 9.2.14.使用以下型号:
from django.db import models
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Foo(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
bar = GenericForeignKey('content_type', 'object_id')
class Bar(models.Model):
foos = GenericRelation(Foo, related_query_name='bars')
class Meta:
abstract = True
class BarX(Bar):
name = models.CharField(max_length=10, default='bar x')
class BarY(Bar):
name = models.CharField(max_length=10, default='bar y')
Run Code Online (Sandbox Code Playgroud)
创建一些实例来演示我的问题:
>>> bar_x = BarX.objects.create()
>>> bar_y = BarY.objects.create()
>>> foo1 = Foo.objects.create(bar=bar_x)
>>> foo2 = Foo.objects.create(bar=bar_y)
>>> foo1.bar.name
u'bar x'
>>> foo2.bar.name
u'bar y'
Run Code Online (Sandbox Code Playgroud)
我无法遍历django中的GFK,尝试过滤引发异常,并显示一条消息,建议添加GenericRelation
.但是使用通用关系,通过相关的查询名称bars
,无法可靠地工作.例如:
>>> [foo.bar.name for foo in Foo.objects.all()]
[u'bar x', u'bar y'] # in a pure python loop, it's working
>>> Foo.objects.filter(bar__name='bar x')
FieldError: Field 'bar' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.
>>> Foo.objects.values_list('bars__name', flat=1)
[None, u'bar y'] # but why None is returned in here?
>>> Foo.objects.filter(bars__name='bar x')
[] # why no result here?
>>> Foo.objects.filter(bars__name='bar y')
[<Foo: Foo object>] # but this one works?
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
未来读者的注意事项: 模板化在Django 1.9 related_query_name
上GenericRelation
无法正常工作.
增加了在Django 1.10是related_query_name现在支持应用标签和使用"%(app_label)s"和"%(类)S"串类插值,后修正为#25354被合并.
如果您使用的是Django 1.10,您可以继续GenericRelation
将抽象基类和模板放在一起,related_query_name='%(app_label)s_%(class)s'
以确保子类的唯一性.
kon*_*iik 19
一般来说,不可能以GenericForeignKey
你正在尝试的方式遍历这个方向.A GenericForeignKey
可以指向应用程序中的任何模型,不仅仅是Bar
它的子类.出于这个原因,Foo.objects.filter(bar__somefield='some value')
目前无法知道您想到的目标模型,因此无法确定目标模型所具有的字段.事实上,在执行这样的查询时,没有办法选择要加入的数据库表 - 它可以是任何表,具体取决于值Foo.content_type
.
如果您确实想在连接中使用通用关系,则必须GenericRelation
在该关系的另一端定义一个.这样你就可以让Django知道它应该在另一边寻找哪个模型.
例如,您可以创建BarX
和BarY
模型是这样的:
class BarX(Bar):
name = models.CharField(max_length=10, default='bar x')
foos = GenericRelation(Foo, related_query_name='bar_x')
class BarY(Bar):
name = models.CharField(max_length=10, default='bar y')
foos = GenericRelation(Foo, related_query_name='bar_y')
Run Code Online (Sandbox Code Playgroud)
如果执行此操作,则可以执行以下查询:
Foo.objects.filter(bar_x__name='bar x')
Foo.objects.filter(bar_y__name='bar y')
Run Code Online (Sandbox Code Playgroud)
但是,您必须选择一个目标模型.这是一个你无法以任何方式真正克服的限制; 每个数据库连接都需要事先知道它在哪个表上运行.
如果您绝对需要同时允许BarX
和BarY
作为目标,则应该能够使用Q
表达式在查询过滤器中明确地列出它们:
Foo.objects.filter(Q(bar_x__name='bar x') | Q(bar_y__name='bar y'))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6061 次 |
最近记录: |