Django - 在重复键上保存()更新

Pie*_*NAY 21 django save insert-update unique-constraint

我的应用程序很少,允许用户对视频进行评级.

用户只能评价一次.所以我已经定义了模型的唯一性.

但他应该能够改变他的比率.所以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'
Run Code Online (Sandbox Code Playgroud)

如果我

rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=2)
rate.save()
Run Code Online (Sandbox Code Playgroud)

它正在保存评级,但如果我

rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=3)
rate.save()
Run Code Online (Sandbox Code Playgroud)

我得到了正常的错误

IntegrityError: (1062, "Duplicate entry '1-1-1' for key 'user_id'")
Run Code Online (Sandbox Code Playgroud)

即使我使用force_update=True(因为仅基于主键)

有没有办法更新评级,如果它已经存在而不必检查之前的数据?

Dan*_*man 36

要更新现有评级,您实际上必须拥有要更新的评级.如果您知道该对象可能不存在,请使用get_or_create:

rate, created = VideoRate.objects.get_or_create(user_id=1, video_id=1, crit_id=1)
rate.rate = 2
rate.save()
Run Code Online (Sandbox Code Playgroud)

您可以使用update()以下方法来简化流程:

VideoRate.objects.filter(user_id=1, video_id=1, crit_id=1).update(rate=2)
Run Code Online (Sandbox Code Playgroud)

但如果评级不存在,这将无声地失败 - 它不会创建一个.

  • 不,因为这是MySQL特定的扩展,Django适用于一系列数据库. (3认同)

Fal*_*gel 8

首先,您必须检查评级是否存在.所以,你既可以用什么丹尼尔·罗斯曼说或使用存在,但你不能因为有更新的简单更新解决这个不创造新的纪录......

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()
Run Code Online (Sandbox Code Playgroud)

您可以使用默认值来传递exrta参数,因此如果它是一个插入,将创建包含所有必需信息的数据库记录,您不需要再次更新它...

文档

更新:这个答案很老,就像问题一样.正如@peterthomassen所说,Django现在有了update_or_create()方法