0

我正在尝试提供用户注册表单,而无需手动输入用户名。我设置了一个身份验证后端,以便用户可以使用电子邮件地址进行身份验证,并且可以使用 Django 管理员用户登录。这个想法是我的应用程序会创建一个电子邮件地址的 SHA1 哈希值,以存储为 Django 用户名,而用户永远不会看到这个。

我从我的注册 html 模板中删除了用户名字段,但我不确定我应该如何或在哪里以编程方式生成用户名。我认为它应该在 RegistrationForm 的 clean_username 方法中,但是当我使用没有用户名字段的模板时,不会调用该方法。

任何帮助肯定会受到赞赏。

4

2 回答 2

1

我让它工作。不得不直接修改注册的查看方式和默认注册后端,感觉不太好。我更愿意在我自己的代码中进行这些更改,并且仍在努力进行这些更改,但这确实有效。

我是这样做的:

  1. 创建了一个名为 RegBackend 的自定义注册后端,它根据电子邮件地址生成一个 sha1 哈希,然后将 hexdigest 存储为用户名,最后返回一个 User 对象。

  2. 将 urls.py 中的寄存器映射到我在步骤 1 中创建的新 RegBackend

  3. 修改了 django-registration 的视图注册方法以创建随机用户名,以便表单验证,但我从不保留随机用户名。我复制了 request.POST 字典并将这个随机用户名设置为副本的字典键之一,称为 data['username']。然后我在创建 form_class 的实例时使用数据变量。在表单上调用 is_valid() 会返回 false,因为我从模板中删除了用户名,但是 Django 需要用户名才能注册,所以我需要提供一些东西

我没有对随机用户名使用 sha1 哈希,因为 Django 用户名只能是 30 个字符,而 sha1 哈希是 40。奇怪的是,自定义注册后端没有抱怨并且可以存储 sha1 哈希,但是表单提交时会因为长度而产生错误。

_ init _.py(我复制了现有的 DefaultBackend 并使用 SHA1 部分进行了修改)

from django.conf import settings
from django.contrib.sites.models import RequestSite
from django.contrib.sites.models import Site

from registration import signals
from registration.forms import RegistrationForm
from registration.models import RegistrationProfile

import hashlib

class RegBackend(object):

def register(self, request, **kwargs):

hash_user = hashlib.sha1()
hash_user.update(kwargs['email'])

    username, email, password = hash_user.hexdigest(), kwargs['email'], kwargs['password1']

    if Site._meta.installed:
        site = Site.objects.get_current()
    else:
        site = RequestSite(request)
    new_user = RegistrationProfile.objects.create_inactive_user(username, email,
                                                                password, site)
    signals.user_registered.send(sender=self.__class__,
                                 user=new_user,
                                 request=request)
    return new_user

    #omitted other code from DefaultBackend that I didn't modify

网址.py

url(r'^register/$', register, {'backend': 'registration.backends.default.RegBackend', 'form_class': UserRegistrationForm}, name='registration_register'),

注册/views.py

def register(request, backend, success_url=None, form_class=None,
             disallowed_url='registration_disallowed',
             template_name='registration/registration_form.html',
             extra_context=None):

    backend = get_backend(backend)
    if not backend.registration_allowed(request):
        return redirect(disallowed_url)
    if form_class is None:
        form_class = backend.get_form_class(request)

    if request.method == 'POST':
        # I added the next two lines
        data = request.POST.copy()
        data['username'] = ''.join([choice(letters) for i in xrange(30)])
        form = form_class(data=data, files=request.FILES)
        if form.is_valid():
            new_user = backend.register(request, **form.cleaned_data)
            if success_url is None:
                to, args, kwargs = backend.post_registration_redirect(request, new_user)
                return redirect(to, *args, **kwargs)
            else:
                return redirect(success_url)

    else:
        form = form_class()

    if extra_context is None:
        extra_context = {}
    context = RequestContext(request)
    for key, value in extra_context.items():
        context[key] = callable(value) and value() or value

    return render_to_response(template_name,
                              {'form': form},
                              context_instance=context)
于 2011-08-14T00:21:33.547 回答
0

您可能正在考虑子类化RegistrationForm然后覆盖该clean方法(不过我不喜欢这样,因为 clean 方法有明确的目的,请参阅https://docs.djangoproject.com/en/dev/topics/forms/modelforms/ #overriding-the-clean-method

一个更简单的解决方案可能是提示用户输入他们的电子邮件地址,然后处理该表单以生成您的用户名,并将该值register作为额外的上下文传递给视图。然后,不要删除用户名字段,而是为其分配散列值并将其隐藏在模板中。这样,您就不必弄乱 django-registration 本身。

有关该论点的更多信息,请参阅https://bitbucket.org/ubernostrum/django-registration/src/fad7080fe769/registration/views.py 。extra_context

于 2011-08-13T01:06:54.170 回答