2011-06-17 130 views
18

我有一個小應用程序,它允許用戶評價一個視頻。Django - 保存()更新重複密鑰

用戶只能打分一次。 所以我定義了模型的唯一性。

但他應該能夠改變他的速度。 所以save()應該重複鍵

class VideoRate(models.Model): 
    """Users can Rate each Video on the criterias defined for the topic""" 
    user = models.ForeignKey(User) 
    video = models.ForeignKey(VideoFile) 
    crit = models.ForeignKey(VideoCrit) 
    rate = models.DecimalField(max_digits=2, decimal_places=1, choices=RATE_CHOICES) 
    class Meta: 
    unique_together = (('user', 'video', 'crit'),) 
    verbose_name = 'Video Rating' 

更新如果我

rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=2) 
rate.save() 

它節省了評級,但如果我

rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=3) 
rate.save() 

我得到正常的錯誤

IntegrityError: (1062, "Duplicate entry '1-1-1' for key 'user_id'") 

即使我使用force_update=True(因爲僅基於主鍵)

有沒有更新評級的方法,如果它已經存在,而無需事先檢查數據?

回答

28

要更新現有評分,您實際上必須擁有要更新的評分。如果您知道對象可能不存在,使用get_or_create

rate, created = VideoRate.objects.get_or_create(user_id=1, video_id=1, crit_id=1) 
rate.rate = 2 
rate.save() 

您可以走捷徑的過程中通過使用update()

VideoRate.objects.filter(user_id=1, video_id=1, crit_id=1).update(rate=2) 

但如果評價不存在,這將失敗默默 - 它將不會創建一個。

+0

+1:第一個選項會做2或3個查詢,而第二個會做1。 – sdolan 2011-06-17 08:00:15

+0

似乎還不錯。你的意思是Django不能執行'INSERT INTO ... ON DUPLICATE KEY UPDATE ...'? – 2011-06-17 09:11:51

+3

不,因爲這是一個特定於MySQL的擴展,並且Django可以處理一系列數據庫。 – 2011-06-17 09:20:48

7

首先,您必須檢查評級是否存在。所以,你既可以用什麼丹尼爾·羅斯曼說或使用存在,但你不能用一個簡單的更新解決了這個,因爲更新不創造新的紀錄......

rating = 2 
rate, created = VideoRate.objects.get_or_create(user_id=1, video_id=1, crit_id=1, 
    defaults={'rate':rating})#if create, also save the rate infdormation 

if not created:# update 
    rate.rate = rating 
    rate.save() 

您可以使用默認通過exrta參數,因此,如果它是一個插入,數據庫記錄將與所有需要的信息來創建,你並不需要更新一次......

Documentation

更新:這個答案就像問題一樣古老。至於@peterthomassen提到,Django現在有update_or_create()方法

+0

'defaults'關鍵字也非常有趣 – 2011-10-07 07:03:01

+1

來自'defaults'參數的值也用於在數據庫中不需要創建對象的情況下進行更新,請參閱https://docs.djangoproject.com /en/1.11/ref/models/querysets/#update-or-create。因此,你的代碼中的「if」部分是無操作的。 – peterthomassen 2017-09-25 22:05:39

+0

@peterthomassen感謝您的通知。更新了答案。 – FallenAngel 2017-09-26 12:38:38