【问题标题】:Auto-generating username when adding a user with django使用 django 添加用户时自动生成用户名
【发布时间】:2018-01-19 03:37:18
【问题描述】:

我正在尝试将用户名保存为名字,同时从 django 管理员添加用户。目前它在用户名字段中保存None,因为我在自定义模型中排除了username

admin.py--

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from .models import UserProfile
from .forms import SignUpForm

class ProfileInline(admin.StackedInline):
    model = UserProfile
    can_delete = False
    verbose_name_plural = 'Profile'
    fk_name = 'user'


class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )
    list_display = ('email', 'first_name', 'last_name', 'is_staff')
    list_select_related = ( 'profile', )

    exclude = ('username',)

    fieldsets = (
        ('Personal information', {'fields': ('first_name', 'last_name', 'email', 'password')}),
        ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
        ('Important dates', {'fields': ('last_login', 'date_joined')}),
    )

    add_fieldsets = (
        ('None', {
            'classes': ('wide',),
            'fields': ('first_name','last_name', 'email', 'password1', 'password2')}
        ),
    )


    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)


admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

forms.py

from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Field
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteField
from phonenumber_field.formfields  import PhoneNumberField
from . import models
from captcha.fields import ReCaptchaField


class SignUpForm(forms.Form):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    phone_number = PhoneNumberField(label=_("Phone (Please state your country code eg. +44)"))
    organisation = forms.CharField(max_length=50)
    email = forms.EmailField()
    password1 = forms.CharField(max_length=20)
    password2 = forms.CharField(max_length=20)
    captcha = ReCaptchaField(attrs={'theme' : 'clean'})



    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        """
        profile, created = models.UserProfile.objects.get_or_create(user=user)
        profile.phone_number = self.cleaned_data['phone_number']
        profile.organisation = self.cleaned_data['organisation']
        profile.save()
        user.save()
        """
        up = user.profile
        up.phone_number = self.cleaned_data['phone_number']
        up.organisation = self.cleaned_data['organisation']
        user.save()
        up.save()

models.py --

from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from easy_thumbnails.fields import ThumbnailerImageField
from ciasroot.settings import THUMBNAILER_SIZES, UPLOAD_PATH
from ciasroot.constants import GENDERS, LANGUAGES
from ciasroot.util import HashedPk
from phonenumber_field.modelfields import PhoneNumberField
import math, decimal, datetime, os
import uuid

    def random_username(sender, instance, **kwargs):
        if not instance.username:
            instance.username = uuid.uuid4().hex[:30]
            models.signals.pre_save.connect(random_username, sender=User)

class UserProfile(models.Model, HashedPk):
    user = models.OneToOneField(User, unique=True, related_name ='profile')
    job_title = models.CharField(max_length=128, blank=True, null=False, default="")
    website = models.URLField(max_length=255, blank=True, null=True)
    organisation = models.CharField(max_length=50, blank=True, null=True, default="")
    phone_number = PhoneNumberField( blank=True, null=True)

    def __str__(self):
        return self.user.get_full_name()

    def save(self, *args, **kwargs):
        super(UserProfile, self).save(*args, **kwargs)
        LookupSuggest.add("job_title", self.job_title)

如何插入用户名作为名字并使自定义字段(即电子邮件)成为“必填”。现在密码 1 和密码 2 字段是必填的。

非常感谢任何帮助/链接。

【问题讨论】:

  • 用户名是只读的吗?
  • 是不可编辑的字段。管理员可以查看它。
  • 您是否使用电子邮件登录?在这种情况下,您还需要确保它是唯一的
  • 是的,我也需要这样做。我试图弄清楚用户名和必填字段的事情。我在前端使用了 allauth 应用程序,但不幸的是它对后端没有影响
  • 好的,我的答案也添加了链接

标签: python django


【解决方案1】:

您可以将用户名定义为只读字段。

def user_first_name(obj):
    return obj.first_name

user_firstname.short_description = 'Firstname'

class CustomUserAdmin(UserAdmin):
    readonly_fields = ('user_firstname')
    inlines = (ProfileInline, )
    list_display = ('email', 'user_first_name', 'last_name', 'is_staff')
    list_select_related = ( 'profile', )

    exclude = ('username',)
    ...

关于验证电子邮件的第二个问题,为CustomUserAdmin 定义一个表单。

class CustomUserAdmin(UserAdmin):
    ...
    form = CustomUserAdminForm 

class CustomUserAdminForm(forms.ModelForm):
    def clean_email(self):
       if not self.cleaned_data['email']:
           raise forms.ValidationError("Email is required")

       return self.cleaned_data['email']

或者:

class CustomUserAdminForm(forms.ModelForm):
    email = forms.EmailField(required=True)

【讨论】:

  • 我尝试了电子邮件验证,但验证失败。我使用了第二种方法。关于用户名,我希望此字段值与 first_name 相同。
  • 我不确定我是否完全理解您的评论。但是,obj.firstnameuser_firstname 中返回。如果你想给它一个不同的标签,你可以在short_description中设置。
  • 类似于 user_first_name.username = 'Firstname' 但我不明白这里的 'Firstname' 是什么。
  • short_description 是只读输入字段的标签文本。我们已经将user_first_name函数中输入字段的值设置为first_name
  • 我试过了,但仍然在用户名字段下保存 None 而不是 first_name 值。
【解决方案2】:

要使用用户的名字自动填充用户名,您应该使用 signal - 将以下内容添加到您定义 UserProfile 的 models.py

def set_username(sender, instance, **kwargs):
    if not instance.username:
        instance.username = instance.first_name
models.signals.pre_save.connect(set_username, sender=User)

这样做的问题是,如果您有两个名字相同的用户,则用户名不会是唯一的,因此您会从数据库中收到完整性错误。您可以检查唯一性并附加一个数字,直到获得唯一值:

def set_username(sender, instance, **kwargs):
    if not instance.username:
        username = instance.first_name
        counter = 1
        while User.objects.filter(username=username):
            username = instance.first_name + str(counter)
            counter += 1
        instance.username = username
models.signals.pre_save.connect(set_username, sender=User)

或者,如果您根本不使用用户名,您可以使用 uuid 将其设置为随机唯一值:

import uuid

def random_username(sender, instance, **kwargs):
    if not instance.username:
        instance.username = uuid.uuid4().hex[:30]
models.signals.pre_save.connect(random_username, sender=User)

如果您打算使用电子邮件而不是用户名登录,您还需要强制电子邮件唯一性,将电子邮件添加到管理员用户创建表单 - 这应该可以满足您的需要:https://gist.github.com/gregplaysguitar/1184995

【讨论】:

  • 我已经用 forms.py 和 models.py 更新了帖子。 allauth 应用程序正在将用户名保存为名字。我将用户名字段更改为不唯一,并将电子邮件设置为唯一。只有电子邮件登录。它适用于前端用户注册过程。我尝试使用随机唯一 ID,但它再次保存“无”
  • 信号需要在models.py文件中连接。将 random_username 部分移动到 models.py 的顶层
  • 并确保 models.signals.pre_save.connect 部分也在顶层,它不是函数的一部分
  • models.py 已在帖子中更新。它仍在保存“无”。
  • 将 random_username 部分移动到 models.py 的顶层
【解决方案3】:

要生成一个随机的唯一用户名,请使用此

import uuid

def random_username(sender, instance, **kwargs):
    if not instance.username:
        instance.username = uuid.uuid4().hex[:30]
models.signals.pre_save.connect(random_username, sender=settings.AUTH_USER_MODEL)

【讨论】:

    【解决方案4】:

    这是我的代码

        import string
    import random
    
    from django.contrib import redirects
    from django.contrib.auth.models import User
    from django.shortcuts import render
    
    from accounts.models import RegisterIndividualModel
    
    def signup_individual(request):
            if request.method == 'POST':
            firstname = request.POST['individual-firstname']
            lastname = request.POST['individual-lastname']
            email = request.POST['individual-email']
            password = request.POST['individual-password']
            gender = request.POST['individual-gender']
            number = request.POST['individual-phone']
    
            # generating random username
            letters = string.ascii_uppercase
            username = firstname + (''.join(random.choice(letters) for i in range(5)))
    
            new_individual_user = RegisterIndividualModel(firstname=firstname, lastname=lastname, username=username,
                                                      email=email, password=password, gender=gender, number=number)
            new_individual_user.save()
            return render(request, 'feed/feed.html')
    

    【讨论】:

    • 您好,欢迎来到 Stackoverflow!您能否为您的解决方案添加一些上下文?谢谢!
    • 请检查以上答案更新,谢谢
    • 很抱歉给您带来了误会。当我说“上下文”时,我的意思是解释为什么您的答案有效以及它的作用,而不是添加上下文代码。我希望这能解决问题!
    猜你喜欢
    • 2011-10-26
    • 2021-11-11
    • 1970-01-01
    • 2021-04-09
    • 2015-03-13
    • 2016-05-10
    • 2020-01-10
    • 2021-03-22
    • 1970-01-01
    相关资源
    最近更新 更多