我使用django序列化程序序列化了几个对象,但问题是每个序列化都从db中查询foerign键的id,而不是仅仅从对象中获取它。
class QBAccount(CompanyModel):
company = models.ForeignKey(Company)
>>> from deretoapp.models import QBAccount
>>> import logging
>>> l = logging.getLogger('django.db.backends')
>>> l.setLevel(logging.DEBUG)
>>> l.addHandler(logging.StreamHandler())
>>> a = QBAccount.allobjects.all()[0]
>>> from django.core import serializers
>>> serializers.serialize('python', [a])
(0.000) SELECT `deretoapp_company`.`id`, ... FROM `deretoapp_company` WHERE `deretoapp_company`.`id` = 45995613-adeb-488f-9556-d69e856abe5f ; args=(u'45995613-adeb-488f-9556-d69e856abe5f',)
[{'pk': u'3de881eb-8409-4089-8de8-6e24f7281f37', 'model': u'deretoapp.qbaccount', 'fields': {... 'company': u'45995613-adeb-488f-9556-d69e856abe5f' ....}}]
有没有办法在不修改django代码的情况下改变这种行为?我知道a.company.id
将查询公司表(这在理想世界中不应该发生)但是在序列化程序中是否有一个选项,以便它执行像a.company_id
这样不会查询db的内容
>>> django.VERSION
(1, 3, 1, 'final', 0)
答案 0 :(得分:1)
我最后修改了django python序列化程序,以便它直接获取引用对象的id而不是从db获取它
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer
class Serializer(PythonSerializer):
internal_use_only = False
def handle_fk_field(self, obj, field):
if not self.use_natural_keys:
# directly get the id
self._current[field.name] = getattr(obj, field.attname)
return
return super(Serializer, self).handle_fk_field(obj, field)
我不确定它是否会处理所有ForeighKey
用例,但它适用于company = models.ForeignKey(Company)
等简单案例
还需要在settings.py
中注册序列化程序SERIALIZATION_MODULES = { 'python' : 'myapp.serializers.python' }
我还为此提交了bug,现在已在django trunk中修复。 see changset
答案 1 :(得分:0)
您应该使用Natural Keys序列化。
基本上,这需要您在外键引用模型上定义一个名为natural_key
的方法,它返回您希望拥有的字段,代替pk
来自文档:
class Person(models.Model):
objects = PersonManager()
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthdate = models.DateField()
def natural_key(self):
return (self.first_name, self.last_name)
class Meta:
unique_together = (('first_name', 'last_name'),)
然后在序列化期间将参数use_natural_keys
设置为True
。
再次,从文档:
>>> serializers.serialize('json', [book1, book2], indent=2, use_natural_keys=True)
答案 2 :(得分:0)
我正在做的是为了避免额外的查询似乎也不是很有效,但它可以解决问题:将select_related(...)
添加到原始查询集以在初始查询中加载相关对象。
例如:
a = QBAccount.allobjects.select_related('company').all()[0]