3

对于将自定义字段添加到 django-registration 注册表单/流程这一看似简单的问题,我对提供的答案范围越来越感到困惑。这应该是该软件包的默认记录方面(听起来不是忘恩负义,只是因为它是一个装备精良的软件包),但该问题的解决方案令人眼花缭乱。

谁能给我最简单的解决方案来获取默认注册注册页面中包含的 UserProfile 模型数据?

更新:

我最终使用了 Django Registration 自己的信号来给我这个 hacky 修复。它特别难看,因为我不得不try在处理我的布尔值的 POST 属性上使用,因为我发现如果复选框留空,则不会返回任何内容。

将不胜感激有关改进这一点或最佳实践的任何建议。

我的应用程序/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()

注册应用程序/forms.py

class RegistrationForm(forms.Form):

    # default fields here, followed by my custom field below

    receive_email = forms.BooleanField(initial=True, required=False)

谢谢

4

2 回答 2

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

要使用自定义后端,您可以提供单独的 url。在包含默认 URL 之前,请编写 2 个指向您的自定义后端的 conf。Url 按照定义的顺序进行测试,因此如果您在包含默认值之前定义这两个,则这两个将在测试默认值之前捕获。

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')),

文档实际上描述了所有这些,但它们并不是特别易于访问(没有阅读文档)。它们都包含在项目中,我在这里浏览它们。

于 2012-10-04T18:32:16.733 回答
1

我最终使用了 Django Registration 自己的信号来解决这个问题。

我会在某个时候清理 try/except 流程。dokkaebi 在上面还指出,当复选框为空时,我可能能够评估 request.GET 参数。

我的应用程序/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()

注册应用程序/forms.py

class RegistrationForm(forms.Form):

    # default fields here, followed by my custom field below

    receive_email = forms.BooleanField(initial=True, required=False)
于 2012-10-05T00:46:54.967 回答