【发布时间】:2021-05-10 19:42:33
【问题描述】:
我有一个通用的用户档案模型,它有几个角色——客户、翻译和编辑。我正在使用与我在帐户应用程序中创建的扩展用户模型的一对一关系,并且我正在使用 Django post_save 信号自动创建与用户相关的配置文件实例,它工作得很好。 现在问题来了:我需要具有特定于角色的配置文件模型,例如客户端配置文件、翻译配置文件等,并且我再次尝试使用 Django post_save 信号创建与主 UserProfile 模型相关的 {role} 配置文件对象和我收到以下错误:
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.
用户模型:
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
【问题讨论】:
标签: python django django-models