2011-10-10 74 views
1

比方說,我有一個模型椰子:Django的:另一個模型的方法使用一個模型實例

class Coconut(models.Model): 
    carrier = models.ForeignKey('birds.Swallow') 
    husk_color = models.IntegerField(Choices=COLORS) 
在某些情況下,我想設置視圖承運人或管理命令或其它地方

現在。

然而,在其他情況下,我想默認是一個特定的燕子。

我很想:

BERT_THE_AFRICAN_SWALLOW = Swallow.objects.get(id=7) 
    def set_carrier(swallow=BERT_THE_AFRICAN_SWALLOW): 
     self.carrier = swallow 

顯然,這是不對的,因爲它連接到數據庫中現有的數據。

此外,如果「鳥」應用程序尚未實例化,它會導致測試運行者博克。

那麼正確的方法是什麼?

的時間的一些例子,當我遇到這樣的問題:

  • 分配自動化過程的「創造者」用戶,這實際上是各種各樣的機器人
  • 在VOIP應用,分配特定的過程,以特定的預定義PhoneNumber對象
  • 在自定義授權方案中,組合預定義的權限或權限對象。

回答

1

我的理解是,你真正想要做的是配置某種默認對象。您可以爲此創建一個配置應用程序,以便您可以在管理界面中進行配置,或將其存儲在固定裝置中或其他東西中。

將字符串(配置選項)映射到任何類型的對象的模型都可以。 contenttype應用程序非常適合您需要的那種外鍵。

# models.py 

from django.db import models 
from django.db.contenttypes.models import ContentType 
from django.db.contenttypes import generic 

class ConfigurationOption(models.Model): 

    name = models.SlugField(max_length = 255, unique=True) 

    value_id = models.PositiveIntegerField() 
    value_type = models.ForeignKey(ContentType) 
    value = generic.GenericForeignKey('value_type', 'value_id') 

    class Meta: 
     unique_together = 'value_id', 'value_type' 

然後您還依賴於數據在配置應用程序存在,但現在是作出了明確。

+0

這非常有趣。我可以研究這項技術的歷史嗎? – jMyles

+0

當然有。身份驗證應用程序使用contenttypes來設置權限。 – pvoosten

0

一個選項可以使用模型信號(選擇取決於何時/何地/如何需要值在那裏默認或重載)和代理模型。

https://docs.djangoproject.com/en/dev/ref/signals/#module-django.db.models.signals

使用Django模型繼承您可以創建具有不同崗位/預方法代理模式,共享同一個表。

https://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models

class Coconut(models.Model): 
    carrier = models.ForeignKey('birds.Swallow') 
    husk_color = models.IntegerField(Choices=COLORS) 

class CoconutCarriedByShallow(Coconut): 
    pass 

    class Meta(): 
     proxy = True 

cached_carriers_dict = {} 

def assign_shallow_carrier(sender, instance, **kwargs): 
    import birds.models 
    attrs = {'name': 'Jhon', 'kind': 'super-fast'} 
    carrier = cached_carriers_dict.get(tuple(attrs.items())) 
    if carrier is None: 
     defaults = {'color': 'blue'} 
     carrier, c = birds.models.Swallow.objects.get_or_create(**attrs, defaults= defaults) 
     cached_carriers_dict.update({tuple(attrs.items()): carrier}) 
    instance.carrier = carrier 

models.signals.post_init.connect(assign_shallow_carrier, sender=CoconutCarriedByShallow) 

當然get_or_create並不總是可用的選項,如果沒有燈具,你可能要考慮的另一種選擇。

希望它幫助;)

+0

雖然這是有趣的和內容豐富的,但我沒有看到它解決了我的問題中描述的需求。我如何使用這個來推廣我所描述的模型實例? – jMyles

+0

@jMyles我已經擴展了這個例子 –

+0

我明白你現在要去哪裏。我不喜歡這個,原因很多,其中最重要的就是get_or_create所帶來的性能提升。另外,我不能用pre_save做同樣的事情並修改kwargs嗎? 這兩個問題很小;這是最大的一個:我仍然需要進口鳥類。因此,該testrunner仍然會抱怨。 – jMyles

相關問題