对于向django-registration寄存器表单/流程中添加自定义字段这一看似简单的问题提供的答案范围,我越来越感到困惑。这应该是包的默认的,记录的方面(不是听起来忘恩负义,只是它是一个装备精良的包),但问题的解决方案令人眼花缭乱。
任何人都可以给我一个最简单的解决方案,将UserProfile模型数据包含在默认注册注册页面中吗?
更新
我最终使用了Django Registration自己的信号来给我这个hacky修复。它特别难看,因为我必须在处理我的布尔值的POST属性上使用try
,因为我发现如果留空则复选框什么也没有返回。
对于改进这项或最佳实践的任何建议表示感谢。
我的app / models.py
from registration.signals import user_registered
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User)
event_commitments = models.ManyToManyField(Event, null=True, blank=True)
receive_email = models.BooleanField(default=True)
@receiver(user_registered)
def registration_active_receive_email(sender, user, request, **kwargs):
user_id = user.userprofile.id
user = UserProfile.objects.get(pk=user_id)
try:
if request.POST['receive_email']:
pass
except:
user.receive_email = False
user.save()
注册app / forms.py
class RegistrationForm(forms.Form):
# default fields here, followed by my custom field below
receive_email = forms.BooleanField(initial=True, required=False)
由于
答案 0 :(得分:2)
你看起来像是一种可行的方法。
我查看了django-registration代码,并根据寄存器视图中的以下注释,我提出了另一种解决方案。我不完全确定这是更清洁,但如果你不是信号的粉丝这很好。如果您打算进行更多自定义,这也提供了一个更容易的途径。
# from registration.views.register:
"""
...
2. The form to use for account registration will be obtained by
calling the backend's ``get_form_class()`` method, passing the
``HttpRequest``. To override this, see the list of optional
arguments for this view (below).
3. If valid, the form's ``cleaned_data`` will be passed (as
keyword arguments, and along with the ``HttpRequest``) to the
backend's ``register()`` method, which should return the new
``User`` object.
...
"""
您可以创建自定义后端并覆盖上述方法:
# extend the provided form to get those fields and the validation for free
class CustomRegistrationForm(registration.forms.RegistrationForm):
receive_email = forms.BooleanField(initial=True, required=False)
# again, extend the default backend to get most of the functionality for free
class RegistrationBackend(registration.backends.default.DefaultBackend):
# provide your custom form to the registration view
def get_form_class(self, request):
return CustomRegistrationForm
# replace what you're doing in the signal handler here
def register(self, request, **kwargs):
new_user = super(RegistrationBackend, self).register(request, **kwargs)
# do your profile stuff here
# the form's cleaned_data is available as kwargs to this method
profile = new_user.userprofile
# use .get as a more concise alternative to try/except around [] access
profile.receive_email = kwargs.get('receive_email', False)
profile.save()
return new_user
要使用自定义后端,您可以提供单独的网址。在包含默认网址之前,请写下指向自定义后端的2个confs。网址按定义的顺序进行测试,因此如果您在包含默认值之前定义这两个网址,则会在测试默认值之前捕获这两个网址。
url(r'^accounts/activate/(?P<activation_key>\w+)/$',
activate,
{'backend': 'my.app.RegistrationBackend'},
name='registration_activate'),
url(r'^accounts/register/$',
register,
{'backend': 'my.app.RegistrationBackend'},
name='registration_register'),
url(r'^accounts/', include('registration.backends.default.urls')),
文档实际上描述了所有这些,但它们并不是特别容易访问(没有readthedocs)。它们都包含在项目中,我正在浏览它们here。
答案 1 :(得分:1)
我最终使用了Django Registration自己的信号给我这个修复。
我会在某个时候清理try / except流程。 dokkaebi还指出,我可能能够评估一个复选框留空时的request.GET参数。
我的app / models.py
from registration.signals import user_registered
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User)
event_commitments = models.ManyToManyField(Event, null=True, blank=True)
receive_email = models.BooleanField(default=True)
@receiver(user_registered)
def registration_active_receive_email(sender, user, request, **kwargs):
user_id = user.userprofile.id
user = UserProfile.objects.get(pk=user_id)
try:
if request.POST['receive_email']:
pass
except:
user.receive_email = False
user.save()
注册app / forms.py
class RegistrationForm(forms.Form):
# default fields here, followed by my custom field below
receive_email = forms.BooleanField(initial=True, required=False)