用户没有userprofile

时间:2016-03-30 19:19:46

标签: django

所以我已经使用score这样的字段扩展了我的用户:

models.py:

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

似乎与recommended way

一致

然后我尝试在我的视图中访问用户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)。

EDIT_2

嗨再次!

所以它明确表示我需要的是

  

创建一个post_save处理程序,用于创建新的配置文件   用户对象已创建

当我阅读它时,这似乎很简单,转到链接到的page,这是Django发送的所有信号的列表。我抬头看了post_save,然后说:

  

与pre_save类似,但在save()方法结束时发送。

好吧,所以我查看pre_save并说:

  

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

我已经解释过这样:当我创建我的用户(在我的views.py中)时,应该调用save()方法(到目前为止还没有这种情况),之后应该发送post_save(?),这将在创建User对象时创建新的配置文件!

所以现在我已经准备好开始查看示例了,所以我google:
django post save example
Here看起来我应该添加一些看起来像装饰者@receiver(post_save, ...的东西。 Here看起来我应该改变多个文件并写一个信号定义? This one似乎也意味着多个文件(包括signals.py)

在我第一次想到的时候,它看起来还有很多。这里的任何人都可以解释我是如何做到这一点的,或者向我展示一些关于信号如何工作的好资源?

现在我的create_users视图如下所示:

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)应该添加?我显然在这里迷失了......

10 个答案:

答案 0 :(得分:8)

您必须先为用户创建userprofile

profile = UserProfile.objects.create(user=request.user)

在views.py中,您可以使用get_or_create,以便在用户没有用户配置文件时为用户创建用户配置文件。

player, created = UserProfile.objects.get_or_create(user=request.user)

更新:要在每次制作新用户时自动创建用户个人资料,请使用singals。在myapp/signals.py执行以下操作:

@receiver(post_save, sender=User, dispatch_uid='save_new_user_profile')
def save_profile(sender, instance, created, **kwargs):
    user = instance
    if created:
        profile = UserProfile(user=user)
        profile.save()

答案 1 :(得分:1)

在创建UserProfile时,您所做的任何事情都不会强制创建User对象。处理此问题有两种基本方法:

  1. 如果您始终希望存在UserProfile(在向default提供score值时就是这种情况,请创建一个post_save处理程序在创建User对象时创建新的配置文件(但不是每次都保存它,所以请务必检查处理程序中的created参数。)

  2. 如果预期用户可能没有个人资料,则在尝试访问时需要捕获UserProfile.DoesNotExist个例外。如果经常这样做,请做一些辅助功能。

  3. 更新回答信号问题

      

    这里看起来也应该添加post_save.connect(create_profile, sender=User)

    您需要定义一个名为create_profile的函数,然后如图所示将其连接起来。我通常在包含models.py的{​​{1}}文件中执行此操作,但在这种情况下,发件人是内置的Django模型,并且您已将该模型导入到您定义的文件中sender这是做这件事的地方。它看起来像是:

    UserProfile

答案 2 :(得分:1)

首先在admin.py中注册配置文件模型。

使用./manage.py createsuperuser创建新的超级用户。

使用新的超级用户登录。

在管理面板中,单击配置文件,然后从用户下拉菜单中添加新条目并选择用户并保存。

答案 3 :(得分:1)

我遇到了同样的问题(= 用户存在,配置文件不存在,但从配置文件端引入了 OneToOne 关系)所以我无法登录到管理站点。该应用程序已经在生产中,我无法删除数据库。

解决方案是创建一个临时视图函数 fixme,没有登录要求(但 URL 难以猜测)并访问一次。该视图查询所有 User 对象,然后使用 get_or_create() 反向查询每个 User 的 Profile。如果 Profile 不存在,则已创建。

打印用于通过日志监控成功。最终从生产应用中删除了视图和 URL。

def fixme(request):
    users = User.objects.all()
    for user in users:
        obj, created = Profile.objects.get_or_create(user=user)
        print(user.username,' : ',created)
    print("all done")
    return HttpResponse("It's done.")

答案 4 :(得分: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()语句

答案 5 :(得分:0)

如果您在尝试上述建议时收到此错误,则可能是因为您创建的第一个用户(使用createsuperuser命令)没有配置文件。

我尝试使用该用户登录时收到此错误。我这样解决了:

- 创建一个新用户。

- 撤消更改。 (删除您为个人资料编写的代码或使其成为注释行)

- 登录您的超级用户。

- 对新创建的用户授予管理员授权。

现在您可以删除第一个用户。 (没有个人资料的用户)

答案 6 :(得分:0)

只需尝试使用Shell创建新用户即可访问管理页面,然后从管理页面为旧用户创建配置文件: python manage.py createsuperuser

要访问shell,请在目录项目ine terminall中输入: python manage.py shell

答案 7 :(得分: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)

注意:您必须登录或保存个人资料。

创建帐户后,您应该能够看到自己尚未登录,并且必须登录才能保存个人资料并开始工作。

答案 8 :(得分:0)

进入你的视图,在你的 create_user 函数中执行这些

profile = userprofile()
profile.user = user
profile.save()

我遇到了类似的问题,经过 3 天的研究,我只用上面的 3 行代码就可以解决这个问题。

答案 9 :(得分:0)

我解决了这个问题(Django 3.8.3-Mongodb)。首先,我创建了signals.py,然后在项目中添加了apps.py。

signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile

@receiver(post_save,sender=User)
def update_user_profile(sender,instance,created,**kwargs):
    if created:
        profile = Profile.objects.create(user =instance)

apps.py

from django.apps import AppConfig


class ProfileConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'Profile'

    def ready(self):
        import Profile.signals

views.py

from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.urls.base import reverse
from .forms import ProfileForm
from .models import Profile
from django.shortcuts import redirect, render,get_object_or_404
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm

login_required(login_url="user:login")
def dashboard(request):
    return render(request,"dashboard.html")


@login_required(login_url="user:login")
def get_profile(request):    
    
    profile = get_object_or_404(Profile,user=request.user)
    
    return render(request,"profile.html",{"profile":profile})

@login_required(login_url="user:login")
def update_profile(request):       
    profile = get_object_or_404(Profile, user=request.user)
    form = ProfileForm(instance=profile)
    if request.method=="POST":
        form = ProfileForm(request.POST,request.FILES,instance=request.user.user_profile)
        if form.is_valid():
            form.save()
            messages.success(request,"Profile is updated successfully")
            return HttpResponseRedirect(reverse("profile:profile"))   
        else:
            return render(request,"profile.html",{"form":form})                 
            
    return render(request,"edit.html",{"form":form})