Django - save() 更新重复键

发布于 2024-11-16 09:19:29 字数 967 浏览 4 评论 0原文

我几乎没有允许用户对视频进行评分的应用程序。

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

但他应该能够改变他的利率。 因此 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 (因为仅基于在主键上)

如果评级已经存在,有没有办法更新评级而无需事先检查数据?

I have little application which allows a user to rate a video.

The user can rate only once.
So I have defined the uniqueness on the model.

But he should be able change his rate.
So the save() should update on duplicate key

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'

If I

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

It's saving the rating, but if I

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

I get the normal error

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

Even if I use force_update=True (since based only on primary keys)

Is there a way to update the rating if it already exists without having to check data before ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你怎么这么可爱啊 2024-11-23 09:19:29

要更新现有评级,您实际上必须拥有要更新的评级。如果您知道该对象可能不存在,请使用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)

但如果评级不存在,这将默默失败- 它不会创建一个。

To update an existing rating, you actually have to have the one you want to update. If you know the object may not exist, use get_or_create:

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

You can short-cut the process by using update():

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

But this will silently fail if the rating does not exist - it won't create one.

—━☆沉默づ 2024-11-23 09:19:29

首先,您必须检查评级是否存在。因此,您可以使用 Daniel Roseman 所说的或使用 exists,但您无法通过简单的更新来解决此问题,因为更新不会创建新记录...

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参数,因此如果是插入,数据库记录将使用所有必需的信息创建,您不需要再次更新它...

文档

更新:这个答案就像问题一样很旧。正如 @peterthomassen 提到的,Django 现在有 update_or_create()方法

First, you must check if the rating exists. So you may either use what Daniel Roseman said or use exists, but you can not solve this with a simple update since update do not create new records...

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()

You can use defaults to pass exrta arguments, so if it is an insert, database record will be created with all required information and you do not need to update it again...

Documentation

Update: This answer is quite old just like the question. As @peterthomassen mention, Django now have update_or_create() method

好久不见√ 2024-11-23 09:19:29

Django 4.1 添加了对此类冲突的支持。在后端,它运行 INSERT...ON DUPLICATE KEY UPDATE 查询。

上述单个查询的示例:

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

# updating rate object if it exists, else create one
rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=3)
VideoRate.objects.bulk_create(
    [rate],
    update_conflicts=True,
    update_fields=['rate']
)

Django 4.1 has added the support for such conflicts. In the backend, it runs a INSERT...ON DUPLICATE KEY UPDATE query.

Example of above in a single query:

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

# updating rate object if it exists, else create one
rate = VideoRate(user_id=1, video_id=1, crit_id=1, rate=3)
VideoRate.objects.bulk_create(
    [rate],
    update_conflicts=True,
    update_fields=['rate']
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文