所以我已经使用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)。
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)
应该添加?我显然在这里迷失了......
答案 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
对象。处理此问题有两种基本方法:
如果您始终希望存在UserProfile
(在向default
提供score
值时就是这种情况,请创建一个post_save
处理程序在创建User
对象时创建新的配置文件(但不是每次都保存它,所以请务必检查处理程序中的created
参数。)
如果预期用户可能没有个人资料,则在尝试访问时需要捕获UserProfile.DoesNotExist
个例外。如果经常这样做,请做一些辅助功能。
更新回答信号问题
这里看起来也应该添加
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})