Skip to main content
 首页 » 编程设计

python之Django之无法使用自定义用户模型将用户添加到用户组

2025年01月19日25del

以前,我一直在使用默认的 Django 用户模型,并在用户注册时将用户添加到特定的用户组,在我的 views.py 中使用此代码没有问题:

user.save() user.groups.add(Group.objects.get(name='customers'))

但是,我现在已更改为自定义用户模型,因此我可以删除注册表单中的“用户名”字段,现在此代码不再有效。新用户尝试注册时会抛出此错误消息:

“用户”对象没有属性“组”

我搜索过但找不到这个问题的答案。我对使用 Django 在后端工作还很陌生,所以请在你的答案中描述性很强(即我需要在哪里放置你建议的代码,models.py/views.py/forms.py 等)。任何帮助将不胜感激!

我的模型.py:

from django.db import models 
from django.contrib.auth.models import ( 
    AbstractBaseUser, BaseUserManager 
) 
 
class UserManager(BaseUserManager): 
    def create_user(self, email, first_name, last_name, password=None, is_staff=False, is_admin=False): 
        if not email: 
            raise ValueError("Users must enter an email") 
 
        if not password: 
            raise ValueError("Users must enter a password") 
 
        if not first_name: 
            raise ValueError("Users must enter their first name") 
 
        if not last_name: 
            raise ValueError("Users must enter their last name") 
 
        user_obj = self.model( 
            email = self.normalize_email(email), 
            first_name = first_name, 
            last_name = last_name, 
        ) 
        user_obj.set_password(password) #set and change password? 
        user_obj.admin = is_admin 
        user_obj.staff = is_staff 
        user_obj.save(using=self._db) 
        return user_obj 
 
    def create_superuser(self, email, first_name, last_name, password=None): 
        user = self.create_user( 
            email, 
            first_name, 
            last_name, 
            password=password, 
            is_staff=True, 
            is_admin=True 
        ) 
        return user 
 
class User(AbstractBaseUser): 
    first_name = models.CharField(max_length=255, blank=True, null=True) 
    last_name = models.CharField(max_length=255, blank=True, null=True) 
    email = models.EmailField(max_length=255, unique=True) 
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False) 
    # active = models.BooleanField(default=True) #can login 
    staff = models.BooleanField(default=False) #staff not superuser 
    admin = models.BooleanField(default=False) #superuser 
 
    USERNAME_FIELD = 'email' 
 
    REQUIRED_FIELDS = ['first_name', 'last_name'] 
 
    objects = UserManager() 
 
    def __str__(self): 
        return self.email 
 
    def get_first_name(self): 
        return self.email 
 
    def get_last_name(self): 
        return self.email 
 
 
    def get_short_name(self): 
        return self.email 
 
    def has_perm(self, perm, obj=None): 
        return True 
 
    def has_module_perms(self, app_label): 
        return True 
 
    @property 
    def is_staff(self): 
        return self.staff 
 
    @property 
    def is_admin(self): 
        return self.admin 

形成.py

from django import forms 
from django.contrib.auth import ( 
    authenticate, 
    get_user_model, 
    login, 
    logout, 
    ) 
from django.contrib.auth.forms import ReadOnlyPasswordHashField 
from django.contrib.auth.models import User, Group 
 
 
User = get_user_model() 
 
class UserAdminCreationForm(forms.ModelForm): 
    """A form for creating new users. Includes all the required 
    fields, plus a repeated password.""" 
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput) 
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) 
 
    class Meta: 
        model = User 
        fields = ('email', 'first_name', 'last_name') 
 
    def clean_password2(self): 
        # Check that the two password entries match 
        password1 = self.cleaned_data.get("password1") 
        password2 = self.cleaned_data.get("password2") 
        if password1 and password2 and password1 != password2: 
            raise forms.ValidationError("Passwords don't match") 
        return password2 
 
    def save(self, commit=True): 
        # Save the provided password in hashed format 
        user = super(UserAdminCreationForm, self).save(commit=False) 
        user.set_password(self.cleaned_data["password1"]) 
        if commit: 
            user.save() 
        return user 

View .py

from __future__ import unicode_literals 
from barbers.forms import BarberProfileForm 
from barbers.models import BarberProfile 
from django.contrib.auth.models import User, Group 
from django.contrib.auth import ( 
    authenticate, 
    get_user_model, 
    login, 
    logout, 
    ) 
from django.contrib.auth.decorators import login_required 
from django.http import HttpResponse, HttpResponseRedirect 
from django.shortcuts import redirect, render, get_object_or_404 
from .forms import BarberRegisterForm, UserLoginForm, UserRegisterForm, UserAdminCreationForm 
 
def register_view(request): 
 
    print(request.user.is_authenticated()) 
 
    register_title = "Register" 
    register_form = UserAdminCreationForm(request.POST or None) 
    if register_form.is_valid(): 
        user = register_form.save(commit=False) 
        password = register_form.cleaned_data.get('password') 
        user.set_password(password) 
        user.save() 
        user.groups.add(Group.objects.get(name='customers')) 
        new_user = authenticate(username=user.username, password=password) 
        login(request, new_user) 
        if next: 
            return redirect(next) 
        return redirect("/my-barbers/{0}".format(request.user.id), user=request.user) 
 
    context = { 
        "register_form": register_form, 
        "register_title": register_title, 
    } 
 
    return render (request, "login.html", context) 

请您参考如下方法:

您的自定义作业用户模型是什么?

也许您继承了 AbstractUser 或 AbstractBaseUser。

但是当你需要使用groups时,你必须继承PermissionsMixin

    from django.contrib.auth.models import PermissionMixin 

可以打卡django github code here

部分代码

class PermissionsMixin(models.Model): 
    """ 
    Add the fields and methods necessary to support the Group and Permission 
    models using the ModelBackend. 
    """ 
    is_superuser = models.BooleanField( 
        _('superuser status'), 
        default=False, 
        help_text=_( 
            'Designates that this user has all permissions without ' 
            'explicitly assigning them.' 
        ), 
    ) 
    groups = models.ManyToManyField( 
        Group, 
        verbose_name=_('groups'), 
        blank=True, 
        help_text=_( 
            'The groups this user belongs to. A user will get all permissions ' 
            'granted to each of their groups.' 
        ), 
        related_name="user_set", 
        related_query_name="user", 
    ) 

希望解决好!

添加

这是我的用户模型的一部分。您应该同时继承 BaseUser 和 PermissionsMixin。然后你可以使用 PermissionsMixin 中的 groups。

class JobUser(AbstractBaseUser, PermissionsMixin, TimeStampedModel): 
    email = models.EmailField( 
        verbose_name="Email", 
        max_length=255, 
        unique=True, 
        db_index=True, 
    ) 
    user_type = models.PositiveIntegerField( 
        verbose_name="User type", 
        # 0 - staff 
        # 1 - employer 
        # 2 - employee 
        choices=CHOICES.USER_CHOICES, 
        default=2, 
    ) 
    ... 

So your User model will be like...

class User(AbstractBaseUser, PermissionsMixin): 
    first_name = models.CharField(max_length=255, blank=True, null=True) 
    last_name = models.CharField(max_length=255, blank=True, null=True) 
    email = models.EmailField(max_length=255, unique=True) 
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False) 
    # active = models.BooleanField(default=True) #can login 
    staff = models.BooleanField(default=False) #staff not superuser 
    admin = models.BooleanField(default=False) #superuser 
    ... 

另外不要忘记在代码顶部导入 PermissionMixin。

希望解决好!