gpt4 book ai didi

python - 使用 UserProfile 创建信号时,Django Rest Framework 重复键值违反唯一约束

转载 作者:太空宇宙 更新时间:2023-11-03 18:07:12 26 4
gpt4 key购买 nike

因此,我创建了一个信号,每次在管理员中创建新用户时,该信号都会自动创建用户配置文件。

代码如下所示:

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.get_or_create(user=instance)

一切正常,直到我尝试在 Django Rest Framework API 中创建 UserProfile 扩展模型。

然后我得到一个重复的键值违反了唯一约束

<h1>IntegrityError at /api/v1/space/</h1>
<pre class="exception_value">duplicate key value violates unique constraint &quot;users_userprofile_user_id_key&quot;
DETAIL: Key (user_id)=(61) already exists.
</pre>

如果我删除信号,那么 API 可以正常工作,但管理员将无法自动创建用户配置文件。

我做错了什么?正确的做法是什么?

我相信这是一个常见问题,尽管我找不到任何相关报告..

我使用的是 Django 1.7.1

更新:

class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
avatar = models.ForeignKey(
'core.Multimedia', blank=True, null=True,
related_name='user_profiles_avatares'
)
language = models.ForeignKey('core.Language', blank=True, null=True)
birth_date = models.DateTimeField(blank=True, null=True)
country = CountryField(blank=True, default='PT')
about_me = models.TextField(blank=True, default='')
facebook_token = models.TextField(blank=True, default='')
space_themed_motivation = models.TextField(blank=True, default='')
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
last_login_on = models.DateTimeField(auto_now=True)


class Space(UserProfile):
degree = models.CharField(max_length=200, blank=True)
galleries = models.ManyToManyField('core.Gallery', blank=True, null=True)
contents = models.ManyToManyField('core.Multimedia', blank=True, null=True)

最佳答案

您想在通过 API 创建用户配置文件时创建用户吗?如果是这样,您的模型 View 集中的创建方法如何?如果您使用默认值,我猜您是在发布请求中发送用户。所以这里创建UserProfile时的流程应该是:

  1. 使用用户 ID 发送 POST 请求。该用户创建。
  2. 用户个人资料已在您的 View 中创建。
  3. 由于用户之前创建,因此不应触发此“post_save”信号。

我猜可能会发生什么:

  1. 当您发送请求时,系统不会创建您的 User 实例。
  2. 序列化器验证通过,因为一切正常。
  3. 创建 UserProfile 时,由于您的 User 关系不能为空,因此它会创建一个 User 实例,触发信号并创建您的 UserProfile。
  4. 创建 User 实例后,它会尝试保存新的 UserProfile 实例,但无法保存,因为它已存在于数据库中(由 User 模型中的 post_save 信号创建)。

我在这里附上create方法的源代码以及相应的注释:

def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.DATA, files=request.FILES)

if serializer.is_valid(): # It passes because here there are no new objects created yet
self.pre_save(serializer.object)
self.object = serializer.save(force_insert=True) # It creates the User (triggering the signal) instance and then when saving UserProfile, it give the integrity error
self.post_save(self.object, created=True)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED,
headers=headers)

return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

我的建议:

  1. 更改创建新用户配置文件时要执行的信号,以便添加新用户。这是执行此操作的正常方法(至少我以前是这样做的)。这在管理和 API 中都有效。
  2. 如果 1 不可能,则不提供 UserProfile 端点,而是使用 User 来执行此操作。这样,它就会像在您的管理员中一样工作。
  3. 如果 1 和 2 都不可行,请重写创建方法并创建 User 实例。这样做的问题是,在您的管理员中创建配置文件时,该配置文件将为空

关于python - 使用 UserProfile 创建信号时,Django Rest Framework 重复键值违反唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26652644/

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