2016-08-22 60 views
2

我的內容模型與標記模型具有多對多關係。當我保存一個Content對象時,我想動態地添加這些關係。我以下面的方式做這件事。在Django的保存方法中動態添加多對多關係

# models.py 

def tag_content(content_id): 
    obj = Content.objects.get(pk=content_id) 
    print obj # Checking 
    obj.tags = [1, 2, 3] # Adding the relationships using the Tag IDs 

class Tag(models.Model): 
    name = models.CharField(max_length=255) 

class Content(models.Model): 
    title = models.CharField(max_length=255) 
    is_tagged = models.BooleanField(default=False) 
    tags = models.ManyToManyField(Tag, blank=True) 

    def save(self, *args, **kwargs): 
     super(Content, self).save(*args, **kwargs) 
     if not self.is_tagged: 
      tag_content(self.pk) # calling the tagging method 

換句話說,當內容物被保存,它的標籤字段與3個不同的標籤對象模型。只是爲了讓你知道,我確實在數據庫中有pks = 1,2和3的標籤。

但是,這根本行不通。 save方法調用tag_content方法,因爲print obj語句有效。但是,多對多字段未設置並保持空白。有趣的是,如果我在shell中運行以下命令,標記字段將完全設置。

# python manage.py shell 
from myapp.models import * 
obj = Content.objects.get(pk=1) 
tag_content(obj.pk) 

那麼shell的版本是如何工作的,但另一個沒有?任何幫助表示讚賞。

+1

不是你問題的原因,但你爲什麼不將內容項本身傳遞給tag_content而不是pk?然後你不必從數據庫中重新查詢它。 –

+0

好點。會做到這一點。但正如你所說,不是解決我的問題。 –

回答

3

由於Django將這些關係寫入數據庫的方式,您無法在自定義save方法中處理m2m關係。當保存帶有m2m關係的模型實例時,Django首先寫入對象,然後再次進入並寫入適當的m2m關係。由於m2m的東西來「秒」,試圖與自定義保存中的關係工作失敗。

的解決方案是使用一個post-save signal.刪除自定義保存的東西,並添加此下方的模型定義,確保進口receiverpost_save

@receiver(post_save, sender = Content) 
def update_m2m_relationships_on_save(sender, **kwargs): 
    if not kwargs['instance'].is_tagged: 
     tag_content(kwargs['instance'].pk) 

tag_content功能或許應該換is_taggedTrue然後保存實例;如果該布爾值永遠不會翻轉,那麼這可能會在無限循環中運行。你也可以通過在對象,而不是通過在PK:

def tag_content(thing_to_tag): 
    thing_to_tag.tags.add([1,2,3]) 
    thing_to_tag.is_tagged = True 
    thing_to_tag.save() 
    return thing_to_tag 

注意使用.add(),加入到M2M的關係時,這是非常重要的。

+0

好的,我試過了。但是,我不斷收到另一個錯誤:不可用類型'列表'。它引用了add()函數。任何想法爲什麼發生這種情況? –

+1

嘗試添加一組查詢對象而不是數字列表 – souldeux