2010-04-09 55 views
4

Django的post_save信號使用多表繼承Django的post_save信號使用多表繼承車型古怪的行爲

我注意到在使用具有模型時,Django的post_save信號工作方式的古怪行爲模型古怪行爲多表繼承。

我有這兩種模式:

class Animal(models.Model): 
    category = models.CharField(max_length=20) 

class Dog(Animal): 
    color = models.CharField(max_length=10) 

我有一個職位保存回調稱爲echo_category:

def echo_category(sender, **kwargs): 
    print "category: '%s'" % kwargs['instance'].category 
post_save.connect(echo_category, sender=Dog) 

我有這樣的夾具:

[ 
    { 
     "pk": 1, 
     "model": "animal.animal", 
     "fields": { 
      "category": "omnivore" 
     } 
    }, 

    { 
     "pk": 1, 
     "model": "animal.dog", 
     "fields": { 
      "color": "brown" 
     } 
    } 
] 

在的每一個部分程序除了post_save回調之外的情況如下:

from animal.models import Dog 
Dog.objects.get(pk=1).category == u'omnivore' # True 

當我運行syncdb並安裝夾具時,會運行echo_category函數。 syncdb的輸出是:

$ python manage.py syncdb --noinput 
Installing json fixture 'initial_data' from '~/my_proj/animal/fixtures'. 
category: '' 
Installed 2 object(s) from 1 fixture(s) 

這裏的奇怪的事情是狗對象的category屬性是一個空字符串。爲什麼它不像其他地方那樣是「雜食者」?

當我重新從數據庫中post_save回調對象的臨時(希望)解決方法:

def echo_category(sender, **kwargs): 
    instance = kwargs['instance'] 
    instance = sender.objects.get(pk=instance.pk) 
    print "category: '%s'" % instance.category 
post_save.connect(echo_category, sender=Dog) 

這工作,但它不是我喜歡的東西,因爲我必須記住當模型繼承做從另一個模型,它必須再次擊中數據庫。另一個奇怪的是我必須做instance.pk來獲得主鍵。正常的'id'屬性不起作用(我不能使用instance.id)。我不知道這是爲什麼。也許這與爲什麼category屬性沒有做正確的事情有關?

回答

5

這是因爲從夾具裝載loaddata/syncdb命令數據被保存在數據庫中原料:只生成的模型表的字段得到保存,以避免撞上在類層次結構的所有車型數據庫。

但是,當保存模型爲原始時,您會在信號中獲得額外的raw關鍵字參數,因此您可以正確處理該案例。你的信號最終會像:

def echo_category(sender, **kwargs): 
    if kwargs.get('raw', False): 
     instance = sender.objects.get(pk=kwargs['instance'].pk) 
    else: 
     instance = kwargs['instance'] 
    print "category: '%s'" % instance.category 

post_save.connect(echo_category, sender=Dog) 

這種方式,夾具打交道時,你只會得到額外的數據庫查詢(我想這是可以接受的,你的情況)。

關於你的另一個問題:

另一個奇怪的是,我必須做instance.pk獲得主鍵。正常的'id'屬性不起作用(我不能使用instance.id)。我不知道這是爲什麼。

idpk具有略微不同的語義。在您的示例中,Dog對象的idAnimal類中定義的AutoFieldautomagically)。然而,pkDog類中的OneToOneField(再一次,automagically defined)。

在實踐中,兩個字段都始終有相同的值。然而,由於id是來自Animal的字段,因此將不存在Dog對象保存爲原始

希望有所幫助。

編輯:此問題已在django的trac here上報告過。