使用 django-registration 自动生成 Django 用户名

发布于 2024-11-29 18:28:50 字数 302 浏览 1 评论 0原文

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

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

任何帮助都将不胜感激。

I'm trying to provide a user registration form without requiring a username to be manually entered. I setup an authentication backend so that users can authenticate with an email address and that works because I can login with the Django admin user. The idea is that my app would create a SHA1 hash of the email address to be stored as the Django username and the user would never see this.

I removed the username field from my registration html template, but I'm not sure how or where I should be generating the username programmatically. I think it should be in the clean_username method of the RegistrationForm, but that method doesn't get called when I use a template without the username field.

Any help would certainly be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姐不稀罕 2024-12-06 18:28:50

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

我是这样做的:

  1. 创建了一个名为 RegBackend 的自定义注册后端,它根据电子邮件地址生成 sha1 哈希,然后将十六进制摘要存储为用户名,最后返回 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

urls.py

url(r'^register/

registration/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)
, register, {'backend': 'registration.backends.default.RegBackend', 'form_class': UserRegistrationForm}, name='registration_register'),

registration/views.py

I got it to work. I don't feel good about having to modify the registration's view method and the default registration backend directly. I'd prefer to have those changes in my own code and am still working to make those changes, but this does indeed work.

Here's how I did it:

  1. Created a custom registration backend called RegBackend that generates a sha1 hash based on the email address and then stores the hexdigest as the username, finally returning a User object.

  2. Map register in urls.py to the new RegBackend that I created in step 1

  3. Modified the django-registration's view register method to create a random username so that the form validates, but I never persist the random username. I copied the request.POST dictionary and set this random username to one of the copy's dictionary keys called data['username']. Then I use the data variable when creating an instance of the form_class. Calling is_valid() on the form would return false because I removed the username from the template, but Django requires a username for registration, so I needed to supply it something.

I didn't use the sha1 hash for the random username because the Django username can only be 30 characters in length while the sha1 hash is 40. Oddly, the custom registration backend didn't complain and can store the sha1 hash, but the form would generate errors because of the length when submitted.

_init_.py (I copied the existing DefaultBackend and modified with the SHA1 portion)

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

urls.py

url(r'^register/

registration/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)
, register, {'backend': 'registration.backends.default.RegBackend', 'form_class': UserRegistrationForm}, name='registration_register'),

registration/views.py

浅暮の光 2024-12-06 18:28:50

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

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

请参阅 https://bitbucket.org/ubernostrum/django-registration/ src/fad7080fe769/registration/views.py 了解更多信息extra_context 参数。

You might be thinking of subclassing RegistrationForm and then overriding the clean method (I don't like that though, since the clean method has a clear purpose, see https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method)

A simpler solution might be to prompt the user to enter their email address, then process that form to generate your username, and pass that value to the register view as an extra context . Then instead of removing the username field, assign the hashed value to it and hide it in your template. That way, you won't have to mess around with django-registration itself.

See https://bitbucket.org/ubernostrum/django-registration/src/fad7080fe769/registration/views.py for more info on the extra_context argument.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文