修复Django中/agents/路径下的RelatedObjectDoesNotExist错误
我正在开发一个Django CRM网站,在将User关联到组织时遇到问题。注意:用户必须登录才能创建Agent。
model.py
class User(AbstractUser): pass class UserProfile(models.Model): user = models.OneToOneField(User,on_delete=models.CASCADE)# every USER has one profile def __str__(self): return self.user.username class Agent(models.Model): user = models.OneToOneField(User,on_delete=models.CASCADE)# every agent has one user organisation = models.ForeignKey(UserProfile,on_delete=models.CASCADE) def __str__(self): return self.user.email # 创建信号监听用户创建事件,自动生成用户档案 def post_user_created_signal(sender,instance,created,**kwargs): if created: UserProfile.objects.create(user = instance) post_save.connect(post_user_created_signal,sender=User)
views.py
class AgentCreateView(LoginRequiredMixin, generic.CreateView): template_name = "agent_create.html" form_class = AgentModelForm def get_success_url(self): return reverse("agents:agent-list") def form_valid(self, form): agent = form.save(commit=False) agent.organisation = self.request.user.userprofile agent.save() return super(AgentCreateView, self).form_valid(form)
用户尝试创建Agent时出现以下错误:
RelatedObjectDoesNotExist at /agents/
User has no userprofile.
Request Method: GET Request URL: http://127.0.0.1:8000/agents/
Django Version: 4.0.6 Exception Type: RelatedObjectDoesNotExist
Exception Value: User has no userprofile.
Exception Location: C:\Users\LT GM\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\fields\related_descriptors.py, line 461, in get
Python Executable: C:\Users\LT GM\AppData\Local\Programs\Python\Python310\python.exe Python Version: 3.10.4
Server time: Sun, 17 Jul 2022 18:54:40 +0000
问题原因
你的post_save信号仅在新用户创建时自动生成UserProfile,但对于信号启用前就已存在的用户(比如手动创建的超级管理员、早期测试账号),不会自动生成对应的UserProfile记录。当登录用户访问self.request.user.userprofile时,因关联记录不存在抛出异常。
修复方案
方案1:为现有用户批量补全UserProfile
在Django Shell中执行以下命令,遍历所有用户并为无档案的用户创建记录:
from django.contrib.auth import get_user_model from your_app.models import UserProfile # 替换为你的app名称 User = get_user_model() for user in User.objects.all(): UserProfile.objects.get_or_create(user=user)
方案2:修改视图代码,确保访问UserProfile时不会报错
在form_valid方法中使用get_or_create,自动为当前用户创建缺失的UserProfile:
def form_valid(self, form): # 确保当前用户的UserProfile存在,不存在则创建 profile, _ = UserProfile.objects.get_or_create(user=self.request.user) agent = form.save(commit=False) agent.organisation = profile agent.save() return super().form_valid(form)
方案3:优化信号逻辑,避免遗漏
将信号中的create改为get_or_create,即使信号重复触发或用户已存在,也能确保UserProfile存在:
def post_user_created_signal(sender, instance, created, **kwargs): # 无论用户是否刚创建,确保UserProfile存在 UserProfile.objects.get_or_create(user=instance) post_save.connect(post_user_created_signal, sender=User)
内容的提问来源于stack exchange,提问作者DevLeb2022

