Python Django-post_保存创建信号后出现RelatedObjectDoesNotExister错误
我有一个通用的用户配置文件模型,它有几个角色——客户端、翻译人员和编辑器。我在accounts应用程序中创建的扩展用户模型中使用了一对一的关系,我使用Django post_save signal自动创建了一个与用户相关的配置文件实例,效果很好。 现在问题来了:我需要有特定于角色的配置文件模型,如客户端配置文件、转换器配置文件等。我再次尝试使用Django post_save signal创建一个与主UserProfile模型相关的{role}配置文件对象,我得到以下错误:Python Django-post_保存创建信号后出现RelatedObjectDoesNotExister错误,python,django,django-models,Python,Django,Django Models,我有一个通用的用户配置文件模型,它有几个角色——客户端、翻译人员和编辑器。我在accounts应用程序中创建的扩展用户模型中使用了一对一的关系,我使用Django post_save signal自动创建了一个与用户相关的配置文件实例,效果很好。 现在问题来了:我需要有特定于角色的配置文件模型,如客户端配置文件、转换器配置文件等。我再次尝试使用Django post_save signal创建一个与主UserProfile模型相关的{role}配置文件对象,我得到以下错误: Traceback
Traceback (most recent call last):
File "D:\Django\tct\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "D:\Django\tct\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\options.py", line 614, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\views\decorators\cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\sites.py", line 233, in inner
return view(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\views\decorators\debug.py", line 89, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\auth\admin.py", line 99, in add_view
return self._add_view(request, form_url, extra_context)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\auth\admin.py", line 126, in _add_view
return super().add_view(request, form_url, extra_context)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\options.py", line 1653, in add_view
return self.changeform_view(request, None, form_url, extra_context)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\options.py", line 1534, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\options.py", line 1580, in _changeform_view
self.save_model(request, new_object, form, not add)
File "D:\Django\tct\venv\lib\site-packages\django\contrib\admin\options.py", line 1093, in save_model
obj.save()
File "D:\Django\tct\venv\lib\site-packages\django\contrib\auth\base_user.py", line 67, in save
super().save(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\db\models\base.py", line 753, in save
self.save_base(using=using, force_insert=force_insert,
File "D:\Django\tct\venv\lib\site-packages\django\db\models\base.py", line 801, in save_base
post_save.send(
File "D:\Django\tct\venv\lib\site-packages\django\dispatch\dispatcher.py", line 177, in send
return [
File "D:\Django\tct\venv\lib\site-packages\django\dispatch\dispatcher.py", line 178, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
File "D:\Django\tct\src\profiles\models.py", line 73, in create_user_profile
UserProfile.objects.create(user=instance)
File "D:\Django\tct\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "D:\Django\tct\venv\lib\site-packages\django\db\models\query.py", line 447, in create
obj.save(force_insert=True, using=self.db)
File "D:\Django\tct\venv\lib\site-packages\django\db\models\base.py", line 753, in save
self.save_base(using=using, force_insert=force_insert,
File "D:\Django\tct\venv\lib\site-packages\django\db\models\base.py", line 801, in save_base
post_save.send(
File "D:\Django\tct\venv\lib\site-packages\django\dispatch\dispatcher.py", line 177, in send
return [
File "D:\Django\tct\venv\lib\site-packages\django\dispatch\dispatcher.py", line 178, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
File "D:\Django\tct\src\clients\models.py", line 32, in save_client_profile
instance.clientprofile.save()
File "D:\Django\tct\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 421, in __get__
raise self.RelatedObjectDoesNotExist(
Exception Type: RelatedObjectDoesNotExist at /admin/accounts/user/add/
Exception Value: UserProfile has no clientprofile.
通用剖面模型
客户端配置文件模型
具有“角色”字段的自定义注册表单
它正在运行
save_client_profile
,并抱怨UserProfile
没有附加client_profile
。未满足create\u client\u profile
的role==1
条件,因为创建时未设置UserProfile的角色
SignUpForm
的save()
方法当前在内存中设置角色,但不会将其提交到数据库,因为user.save()
只保存用户模型,而不保存其相关的用户配置文件。您需要在user.userprofile.role=self.cleaned\u data.get(“role”)
之后执行user.userprofile.save()
,角色才能持久。谢谢您的回答,但我正在使用用户注册表单填充角色字段,该表单当前继承自django allauth SignupForm类。我认为它工作得很好,而且我在注册视图中可以选择角色。编辑了问题并添加了表单。看起来您没有在save()方法中保存UserProfile,只有用户:user.UserProfile.save()
在设置角色后应该这样做。omg!你说得对。在注册表单的保存功能中保存用户之后,我只需要保存用户配置文件。编辑答案,以便我可以将其标记为已接受。谢谢,太好了,我已经编辑过了。
class User(AbstractUser):
id = models.UUIDField(
_("User ID"), primary_key=True, default=uuid.uuid4, editable=False
)
class UserProfile(models.Model):
# General Info
CLIENT = 1
TRANSLATOR = 2
EDITOR = 3
ROLE_CHOICES = (
(CLIENT, _("Client")),
(TRANSLATOR, _("Translator")),
(EDITOR, _("Editor")),
)
MALE = 1
FEMALE = 2
GENDER_CHOICES = ((MALE, _("Male")), (FEMALE, _("Female")))
user = models.OneToOneField(
User, verbose_name=_("User"), on_delete=models.CASCADE, primary_key=True
)
role = models.PositiveSmallIntegerField(
_("Role"), choices=ROLE_CHOICES, null=True, blank=True
)
bio = models.TextField(_("Bio"), null=True, blank=True)
avatar = models.ImageField(
_("Avatar"), upload_to="profiles/profile/avatar/", blank=True
)
gender = models.PositiveSmallIntegerField(
_("Gender"), choices=GENDER_CHOICES, null=True, blank=True
)
# Contact Info
phone = models.CharField(_("Phone"), max_length=20, null=True, blank=True)
cell = models.CharField(_("Cell"), max_length=20, null=True, blank=True)
id_number = models.CharField(_("ID Number"), max_length=20, null=True, blank=True)
address = models.TextField(_("Address"), null=True, blank=True)
postal_code = models.CharField(
_("Postal Code"), max_length=20, null=True, blank=True
)
website_url = models.URLField(
_("Website URL"), max_length=200, null=True, blank=True
)
instagram_username = models.CharField(
_("Instagram Username"), max_length=200, null=True, blank=True
)
telegram_username = models.CharField(
_("Telegram Username"), max_length=200, null=True, blank=True
)
twitter_username = models.CharField(
_("Twitter Username"), max_length=200, null=True, blank=True
)
# Model Extra
class Meta:
verbose_name = _("User Profile")
verbose_name_plural = _("User Profile")
def __str__(self):
return self.user.username
def get_absolute_url(self):
return reverse("profiles:user_profile_detail", args=[str(self.user.id)])
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
class ClientProfile(models.Model):
profile = models.OneToOneField(
UserProfile, verbose_name=_("User"), on_delete=models.CASCADE, primary_key=True
)
credit = models.IntegerField(_("Credit"), default=0, blank=True)
debt = models.IntegerField(_("Debt"), default=0, blank=True)
referral_code = ULIDField(default=default)
referrals = models.ManyToManyField(
User, verbose_name=_("Referrals"), related_name="client_profile"
)
income = models.IntegerField(_("Income"), default=0, blank=True)
@receiver(post_save, sender=UserProfile)
def create_client_profile(sender, instance, created, **kwargs):
if created:
if instance.role == 1:
ClientProfile.objects.create(profile=instance)
@receiver(post_save, sender=UserProfile)
def save_client_profile(sender, instance, **kwargs):
instance.clientprofile.save()
class CustomSignupForm(SignupForm):
role = forms.ChoiceField(
widget=forms.RadioSelect(), choices=UserProfile.ROLE_CHOICES, required=False, label=_("Role")
)
def save(self, request):
# Ensure you call the parent class's save.
# .save() returns a User object.
user = super(CustomSignupForm, self).save(request)
user.userprofile.role = self.cleaned_data.get("role")
user.save()
# You must return the original result.
return user