django - Django 中主键的重复条目 - 我如何在 Django 中进行 upsert?
问题描述
我正在尝试在 Django 上执行 update_or_create,其中还涉及一些逻辑(由于我使用的字符集的独特性,我必须与 PUT 的最佳实践略有偏差)。
我的视图中有以下代码(仅显示 PUT 方法):
class WordView(APIView):
def put(self, request, user_id):
character = request.data.get('character')
correct = request.data.get('correct')
mistakes = request.data.get('mistakes')
score = request.data.get('score')
if Word.objects.filter(user_id=user_id, character=character).exists():
orig_word = Word.objects.get(user_id=user_id, character=character)
correct = correct + orig_word.correct
mistakes = mistakes + orig_word.mistakes
trials = orig_word.trials + 1
score = (score + (orig_word.score * orig_word.trials)) / trials
pk = orig_word.pk
else:
trials = 1
# Note - I know that pk won't exist on create - just testing update right now
word_saves = {"user_id": user_id, "character": character,
"correct": correct, "mistakes": mistakes, "score": score, "trials": trials, "pk": pk}
serializer = WordSerializer(data=word_saves)
if serializer.is_valid(raise_exception=True):
word_saved = serializer.save()
return Response({"success": "Word character {} saved for user {}".format(word_saved.character, word_saved.user_id)})
然后在我的 WordSerializer 中,我有这个:
class WordSerializer(serializers.Serializer):
user_id = serializers.IntegerField()
character = serializers.CharField()
correct = serializers.IntegerField()
mistakes = serializers.IntegerField()
score = serializers.FloatField()
trials = serializers.IntegerField()
pk = serializers.IntegerField()
def create(self, validated_data):
return Word.objects.update_or_create(**validated_data)
但是,当我在存在具有给定 user_id 和字符的行时发出 PUT 请求时,我得到以下信息:
django.db.utils.IntegrityError: (1062, "Duplicate entry '29' for key 'PRIMARY'")
问题是,我想用我的新值更新数据库中存在的值。我认为那是什么update_or_create
- 一个upsert。
如何使用我目前拥有的代码进行更新插入?
解决方案
您应该使用defaults
关键字参数在调用时传递要更新的字段update_or_create
。您传递的关键字参数defaults
将用于匹配您要更新的现有记录。
在您的情况下,如果user_id
并且character
是模型的唯一标识字段,您应该将这些字段作为关键字传递
class WordSerializer(serializers.Serializer):
def create(self, validated_data):
return Word.objects.update_or_create(
user_id=validated_data.pop('user_id'),
character=validated_data.pop('character'),
defaults=validated_data
)
推荐阅读
- r - 将excel数据库转换为可重现的格式
- python - 如何在pygame中只杀死自己的精灵?
- wordpress - 使用 Vue 显示最近的 WordPress 帖子
- django - 如何在 django 中对搜索结果项进行排序
- redirect - Bambora 支付服务 + React 应用集成
- sql - 使用 Groupby 计数不同的窗口函数
- python - 如何从另一个数据框中给定日期的数据框中获取元素
- forms - 通过表单使用表单上的输入和另一个表中的数据更新表
- google-bigquery - 每月通过三个不同的查询获得 3 个最佳帖子
- javascript - 如何在 ExpressJs 路由器中使用精确匹配