gpt4 book ai didi

python - 在 Django 中,如何找到违反唯一一起约束的行?

转载 作者:搜寻专家 更新时间:2023-10-30 19:47:20 25 4
gpt4 key购买 nike

对于以下 API 端点,

import json

from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponseBadRequest
from django.views.decorators.http import require_POST

from lucy_web.models import UserApn


@login_required
@require_POST
def save_apn(request, version):
player_id = json.loads(request.body).get('player_id')
if player_id:
UserApn.objects.get_or_create(user=request.user, player_id=player_id)
return JsonResponse({'status': 'success'})
else:
return HttpResponseBadRequest()

这是底层模型:

from django.contrib.auth.models import User
from django.db import models
from .timestamped_model import TimeStampedModel


class UserApn(TimeStampedModel):
user = models.ForeignKey(User)
player_id = models.CharField(max_length=255)

调用get_or_create()一直在引发一些 MultipleObjectsReturned 错误。要解决此问题,我想对 userplayer_id 施加一个 unique_together 约束。但是,首先,我必须编写一个数据迁移,以消除违反此唯一在一起约束的行。

我如何编写一个查询来选择这些?目前已提出以下建议:

def remove_duplicate_apns(apps, schema_editor):
UserApn = apps.get_model('lucy_web', 'UserApn')

previous_user_id = None
previous_player_id = None
for apn in UserApn.objects.all().order_by('user_id', 'player_id'):
if apn.user_id == previous_user_id and apn.player_id == previous_player_id:
print(f'deleting {apn} (id: {apn.id})')
apn.delete()
else:
previous_user_id = apn.user_id
previous_player_id = apn.player_id

不过,这似乎也可以在单个查询中完成。

更新

我发现可以将 userplayer_id 这两个字段传递给 .values(),然后检查使用 .distinct() 复制。例如,以下测试通过:

from django.test import TestCase

from django.contrib.auth.models import User
from myapp.models import UserApn


class UserApnTest(TestCase):
def test_1(self):
user = User.objects.create_user(username='jayz')
apn1 = UserApn.objects.create(user=user, player_id='foo')
apn2 = UserApn.objects.create(user=user, player_id='foo')
apn3 = UserApn.objects.create(user=user, player_id='bar')

self.assertEqual(
len(UserApn.objects.values('user', 'player_id')) -
len(UserApn.objects.values('user', 'player_id').distinct()), 1)

但是,问题仍然存在,输出是带有 user_idplayer_id 的字典,但是原始的 id 丢失了,所以我随后无法 get() 重复对象并删除它们。我怎样才能做类似的事情但保留对重复对象的引用?

最佳答案

我设法将重复的 UserApn 分组到以下查询集中:

UserApn.objects.all().difference(UserApn.objects.distinct('user', 'player_id'))

请注意,将多个参数传递给 distinct()仅适用于 PostgreSQL。

关于python - 在 Django 中,如何找到违反唯一一起约束的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51487797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com