gpt4 book ai didi

python - 多个字段到同一个数据库列

转载 作者:太空狗 更新时间:2023-10-29 18:12:34 27 4
gpt4 key购买 nike

我们正在尝试通过 prefetch_related 来加速我们的应用程序.它可以遵循 GenericForeignKey 关系,并且可以使用 __ 更深入,但不幸的是,如果相关模型没有这样的字段,它将失败。

这里是一些模型结构的例子

class ModelA(models.Model):
event_object = models.ForeignKey(SomeModelA)

class ModelB(models.Model):
event = models.ForeignKey(SomeModelB)

class ModelC(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()

因此 ModelC 实例可以指向 ModelAModelB。我可以使用这样的查询集来预取 A 和 B 模型:/code> 或 SomeModelB)

如果我尝试运行

ModelC.objects.all().prefetch_related('content_object', 'content_object__event_object')

如果我只有指向 ModelAModelC 实例,它会工作,但在其他情况下它会失败,因为 ModelB 没有event_object 字段并用 event 代替。

此模型在代码中的许多地方使用,因此重命名该字段不是一个好主意。所以我想知道是否有办法为字段/列创建别名。

我想这样做:

class ModelB(models.Model):
event = models.ForeignKey(SomeModelB)
event_object = models.ForeignKey(SomeModelB, db_column='event_id', related_name='+')

使两个字段指向数据库表中的同一列。但是,这不起作用,因为它破坏了 save 方法。 Django 创建一个 UPDATE SQL 查询,其中一列被放置两次并得到 DatabaseError

有没有办法创建这样的别名?或者也许有另一种解决方案可以使 prefetch_related 不抛出异常?

更新:在save方法中有一个update_fields参数可以用来排除这个字段。但是它是在 1.5 中引入的,我们正在使用 1.4。所以我继续寻找答案。

更新 #2:@shx2 要求我提供回溯。有 2 种可能的回溯。1st - 当第一个对象缺少属性时:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 72, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 97, in __iter__
len(self)
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 89, in __len__
self._prefetch_related_objects()
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 570, in _prefetch_related_objects
prefetch_related_objects(self._result_cache, self._prefetch_related_lookups)
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 1664, in prefetch_related_objects
(attr, first_obj.__class__.__name__, lookup))
AttributeError: Cannot find 'event_object' on ModelB object, 'content_object__event_object' is an invalid parameter to prefetch_related()

如果 prefetch_related 参数对第一个对象有效,那么我得到第二个回溯:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 72, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 97, in __iter__
len(self)
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 89, in __len__
self._prefetch_related_objects()
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 570, in _prefetch_related_objects
prefetch_related_objects(self._result_cache, self._prefetch_related_lookups)
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 1680, in prefetch_related_objects
obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)
File "/home/igor/workspace/projectname/eggs/Django-1.4.2-py2.7.egg/django/db/models/query.py", line 1803, in prefetch_one_level
qs = getattr(obj, attname).all()
AttributeError: 'ModelB' object has no attribute 'event_object'

最佳答案

它看起来像是 django 中的错误或疏忽。作为解决方法,您可以尝试定义一个执行两阶段预取的自定义管理器。

from django.db import models
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType

class PrefetchWorkaroundManager(models.Manager):
def get_queryset(self):
q = super(PrefetchWorkaroundManager, self).get_queryset()
content_typeA = ContentType.objects.get_for_model(ModelA)
content_typeB = ContentType.objects.get_for_model(ModelB)
return q.filter(content_type__pk = content_typeA.id).prefetch_related('content_object', 'content_object__event_object') | \
q.filter(content_type__pk = content_typeB.id).prefetch_related('content_object', 'content_object__event')

class ModelC(models.Model):
...

objects_prefetched = PrefetchWorkaroundManager()

每个希望进行预取的调用者都应该访问 ModelC.objects_prefetched 而不是 ModelC.objects:

ModelC.objects_prefetched.filter(...)

我承认,我没有测试它,所以它可能无法按原样工作。但我相信这种方法是合理的。

关于python - 多个字段到同一个数据库列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15386052/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com