web-dev-qa-db-ja.com

Django-重複キーのsave()更新

ユーザーがビデオを評価できるアプリケーションはほとんどありません。

ユーザーは一度だけ評価できます。そこで、モデルの一意性を定義しました。

しかし、彼は彼の率を変えることができるはずです。したがって、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を使用しても(主キーのみに基づいているため)

以前にデータをチェックせずに評価がすでに存在する場合、評価を更新する方法はありますか?

23

既存の評価を更新するには、実際に更新したい評価が必要です。オブジェクトが存在しない可能性があることがわかっている場合は、_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)
_

ただし、評価が存在しない場合、これは黙って失敗します-評価は作成されません。

37
Daniel Roseman

まず、評価が存在するかどうかを確認する必要があります。したがって、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()

defaultsを使用してexrta引数を渡すことができるため、insert、データベースレコードは必要なすべての情報を使用して作成され、再度更新する必要はありません...

ドキュメント

更新:この回答は質問と同じようにかなり古いものです。 @peterthomassenが言及しているように、Django now have pdate_or_create() method

8
FallenAngel