2013-01-18 225 views
2

我有以下代碼:Django的 - 創建對象和子對象

class Album(models.Model): 
    name = models.CharField(max_length=255, unique=True, null=False) 
    rating = models.ForeignKey("Rating", null=False) 

class Rating(models.Model): 
    value = models.IntegerField(null=False, default=0) 

什麼是創建一個對象(專輯)的最佳方式(在Django的/ Python的哲學)和它的子對象(額定值)並保存它?

我已經做到了這一點:

a = Album() 
a.name = "..." 
r = Rating() 
r.save() 
a.rating = r 
a.save() 

我不喜歡這一點,因爲在創建子對象空的部分是完全沒有用的。 我更喜歡一些簡單的方法,這樣的 - 子對象應自動創建:

a = Album() 
a.name = "..." 
a.save() 

回答

3

你會想看看signals

保存對象時基本上會發送信號。

使用pre_save信號即可創建一個Rating和它之前它被保存在第一次關聯到新Album僅僅指剛。

from django.db.models.signals import pre_save 
from django.dispatch import receiver 
from myapp.models import Album, Rating 

@receiver(pre_save, sender=Album) 
def add_rating_to_album(sender, **kwargs): 

    # If saving a new Album 
    if not instance.id: 

     # Create and save a new rating 
     rating = Rating() 
     rating.save() 

     # Associate it to the Album being saved 
     instance.rating = rating 

    # Continue to normal save with new rating applied 

我沒有測試過這種特定的代碼,但它應該讓你在正確的方向

+0

非常有趣。 這將等於覆蓋保存方法(並在設置評分後調用父代),否? –

+0

類似的,但這是更可擴展的,因爲其他人也可以寫一個信號,也將與你一起運行。覆蓋保存方法可能會導致問題。但是,是的,你可以用'save()'來代替 – rockingskier

+0

不幸的是,這段代碼(pre_save)似乎不起作用。如果未設置評分,我會得到相同的錯誤消息。我不知道爲什麼? –

0

使用信號作爲rockingskier說是一個很好的辦法做到這一點,因爲你的相冊,對象不必瞭解關於評級的任何事情,因此獲得獨立

另一種方式來做到這將是覆蓋相冊的方法save並創建新的評級對象存在,這個代碼是基於例如Django docs

class Album(models.Model): 
    name = models.CharField(max_length=100) 

def save(self, *args, **kwargs): 
    # do something here 
    super(Album, self).save(*args, **kwargs) # Call the "real" save() method. 
    # do anything else 

這可能是一個更簡單的方法做到這一點,但你的專輯模型將被綁定到你的評級模型。

+1

恕我直言,只要專輯有評級領域沒有更多的獨立性;) –