具有标准用户模型的foreginkey模型的RelatedObjectDoesNotExist

时间:2019-07-14 12:48:40

标签: python django

我有这个问题:RelatedObjectDoesNotExist

我将UserProfile添加到我的模型中(目前只有头像可以添加到用户模型中。

添加图片不是强制性的。因此某些userProfile为null。问题是当我编辑Userform和ProfileUserform时。我有一个错误: / accounts / user_edit /中的RelatedObjectDoesNotExist 用户没有个人资料。

我尝试添加尝试:视图除外,但似乎不起作用

Models.Py:

   class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')  # il s'agit d'ajouter des infos au modele User

    #  add any additional attributes needed
    avatar = models.ImageField(upload_to='profile_pics', blank=True) # avatar of the user in director profile_pics

    def __str__(self):
        return self.user.email

Views.py:

@login_required(login_url='account/sign_up.html')
def user_edit(request):
    # Get info from "both" forms
    # It appears as one form to the user on the .html page
    user_form = UserFormEdit(instance=request.user)

    profile_form = UserProfileForm(instance=request.user.profile)


    # Check to see both forms are valid
    if user_form.is_valid() and profile_form.is_valid():
        # Prepare Save User Form to Database
        user = user_form.save()
        profile = profile_form.save(commit=False)

        # Check if they provided a profile picture
        if 'profile_pic' in request.FILES:
            print('found it')
            # If yes, then grab it from the POST form reply
            profile.profile_pic = request.FILES['profile_pic']
        profile.save()
        messages.success(request, 'User updated')

    return render(request, 'account/user_edit.html',
                  {'user_form': user_form,
                   'profile_form': profile_form}
                   )

错误发生在profile_form = UserProfileForm(instance = request.user.profile)

因为请求为空。...

创建用户后,我希望可以添加或编辑UserProfile信息。因此,如果尚不存在,则应呈现一个空的UserProfileForm;如果存在,则应呈现实例user.profile数据

感谢您的帮助

3 个答案:

答案 0 :(得分:1)

您可以检查配置文件是否存在,如果不使用新实例,则可以使用

try:
  profile = request.user.profile
except UserProfile.DoesNotExist:
  profile = UserProfile(user=request.user)
profile_form = UserProfileForm(instance=profile)

答案 1 :(得分:0)

您有一个RelatedObjectDoesNotExist错误的事实是由于用户本身 没有相关的Profile这个事实。因此request.user.profile可能会失败。

如果Profile存在.filter(..).first(),则可以获取{}:

@login_required(login_url='account/sign_up.html')
def user_edit(request):
    user = request.user
    profile = Profile.objects.filter(user=user).first()
    if request.method == 'POST':
        user_form = UserFormEdit(request.POST, request.FILES, instance=request.user)
        profile_form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.instance.user = user
            profile = profile_form.save()
            messages.success(request, 'User updated')
            return redirect('some_view')
    else:
        user_form = UserFormEdit(instance=user)
        profile_form = UserProfileForm(instance=profile)
    return render(
        request,
        'account/user_edit.html',
        {'user_form': user_form, 'profile_form': profile_form}
    )

此外,表单也可以处理文件,我建议您让表单处理工作,因为它通常不那么容易出错,可以执行正确的验证并删除许多样板代码。

答案 2 :(得分:0)

虽然有两个相关的模型并且一个对象仅存在于一个模型中是完全可以的,但在这种情况下,即使它是空的,也总是要有一个配置文件可能会更好。我建议在用户创建时创建一个用户个人资料。

无论如何,如果您想继续使用现有代码,在您看来,处理编辑时创建UserProfile的一种简单方法就是执行以下操作

try:
    profile = request.user.profile
except RelatedObjectDoesNotExist:  # I feel it should actually throw AttributeError here
    profile = UserProfile(user=request.user)  # this is a dummy profile and won't be save until the form is saved
    profile_form = UserProfileForm(instance=profile)

如果您确实想在创建用户时创建配置文件,则可以将其添加到表单或模型的保存中。

# in form
def save(self, *args, **kwargs):
    is_create = self.instance.pk is None
    return_value = super().save(*args, **kwargs)
    if is_create:
        UserProfile.objects.create(user=self.instance)
    return return_value

# or in user model
def save(self, *args, **kwargs):
    is_create = self.pk is None
    super().save(*args, **kwargs)
    if is_create:
        UserProfile.objects.create(user=self)
    return self

# or in the view
def create(request):
    ...
    if form.is_valid():
        user = form.save()
        UserProfile.objects.create(user=self)
    ...