2012-01-27 145 views
2

Django的串行查詢數據庫序列化的幾個對象使用Django序列化,但問題是每個序列化查詢從數據庫中foerign鑰匙的ID,而不是從對象例如只是把它爲forign密鑰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,不會查詢數據庫

>>> django.VERSION 
(1, 3, 1, 'final', 0) 

回答

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_keysTrue

再次,從文檔:

>>> serializers.serialize('json', [book1, book2], indent=2, use_natural_keys=True) 
+0

這將無法避免數據庫查詢,我想'ID即pk'不自然鍵 – 2012-01-27 16:38:48

1

我最後修改Django的蟒蛇序列化,使其直接被引用的,而不是從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) 

得到它的對象的ID,我不知道,如果它需要照顧所有ForeighKey用例,但它適用於簡單情況如company = models.ForeignKey(Company)

還需要註冊seria lizer在settings.py

SERIALIZATION_MODULES = { 'python' : 'myapp.serializers.python' } 

我又提出了bug這一點,這是現在固定在Django樹幹。 see changset

0

我在做什麼,以避免額外的查詢,似乎不是很有效,要麼,但它的伎倆:添加select_related(...)你原來的查詢集加載在初始查詢相關的對象。

例如:

a = QBAccount.allobjects.select_related('company').all()[0]