RelatedObjectDoesNotExist: 用户没有用户资料。

22

所以我已经通过以下方式将用户扩展了字段score

models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    score = models.IntegerField(default=0);

这似乎是沿用推荐的方法

接下来,我尝试在我的视图中访问用户的userprofile

views.py:

player = request.user.userprofile

这似乎也符合推荐的方式,但这就是我出错的地方:

RelatedObjectDoesNotExist
User has no userprofile.

如果我将userprofile更改为其他内容,就会出现另一个错误:

AttributeError
'User' object has no attribute 'flowerpot'

当我尝试以下代码时:

print request.user
print UserProfile.objects.all()

我获得了控制台输出:

post_test1
[]

编辑
我有两个超级用户,七个在扩展用户之前我创建的用户,和一个在扩展用户后我创建的用户(post_test1)。


编辑2

看起来我需要创建一个post_save处理程序,在每次创建User对象时都创建一个新的profile。

当我阅读它时,它似乎很简单,我转到链接的页面,那里是Django发送的所有信号的列表。 我查找了post_save,它说:

像pre_save一样,但在save()方法结束时发送。

好的,所以我查找了pre_save,它说:

这是在模型的save()方法开始时发送的。

我这样解释它:当我创建我的用户(在我的views.py中)时,应该调用save()方法,但直到现在还没有发生过,并且之后应该发送post_save,每当创建User对象时都会创建一个新的profile!

所以现在我准备开始查看示例,于是我谷歌搜索:

django post save example
这里看起来我应该添加类似于装饰器的东西@receiver(post_save, ...
这里看起来我应该更改多个文件并编写一个信号定义?
这个也似乎暗示了多个文件(包括signals.py)。

看起来比我最初想的要复杂得多。 这里是否有人可以解释我应该如何做或向我展示一些关于信号如何工作的好资源?

现在我的create_user视图如下:

def create_user(request):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data["username"]
            password = form.cleaned_data["password1"]
            new_user = User.objects.create_user(username=username, password=password)
            return redirect('play')
    else:
        form = UserCreationForm()

    return render(request, 'antonymapp/create_user.html', {'form': form})

我应该在返回之前调用new_user.save()吗?如果是,为什么到现在为止都能正常工作?我在测试这个视图时创建了一堆用户。看起来还需要在这里添加post_save.connect(create_profile, sender=User)


1
RelatedObjectDoesNotExist 表示没有与 request.user 相关联的 userprofile,这似乎很明显,不是吗? - Shang Wang
我扩展了用户和用户资料,但仍然没有与请求用户相关的用户资料。所以是的,你说得对。这显然是我在这里询问的问题。 - MrJalapeno
你在设置文件中设置了用户配置文件吗?例如,如果你的应用程序名称是base,则需要在你的设置文件中添加以下内容。 AUTH_PROFILE_MODULE = 'base.UserProfile' - abhishekgarg
14个回答

0

只需尝试使用shell创建一个新用户以访问管理员页面,然后在管理员页面为旧用户创建个人资料:python manage.py createsuperuser

要访问shell,在项目目录中的终端中输入: python manage.py shell


0

回答更新后的问题。模型中已经有一个save()方法,每次保存模型时都会调用它(在你的情况下,当你调用create_user()时)。因此,你只需要定义一个处理函数并将其连接到post_save信号上即可。

def create_extension(sender, instance, created, *args, **kwargs):
    if created:
        # do your thing
models.signals.post_save.connect(create_extension, sender=User, dispatch_uid='create_extension')

我通常将处理函数放入一个名为signals.py的单独文件中,并在models.py的末尾添加connect()语句。


0
如果在应用程序设置身份验证之前创建了用户,则需要在终端上创建一个新的超级用户,然后使用该帐户登录。我确定没有像错误所述的那样创建配置文件!

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - mfit

0

虽然有点晚了,但我想分享一下在Django 3.0.8上为我解决问题的方法...

错误: RelatedObjectDoesNotExist: 用户没有档案

这就是导致错误的代码片段:

@login_required
def dashboard(request):
    if request.method == 'POST':
        user_form = UserEditForm(instance=request.user, data=request.POST)
        profile_form = ProfileEditForm(instance=request.user.profile, data=request.POST, files=request.FILES)

注意:您必须登录或创建个人资料才能保存。
在创建账户后,您应该能够看到您未登录,您需要登录以保存个人资料并开始工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接