Django - 使用自定义用户模型将用户添加到用户组时遇到问题



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

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

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

">

用户"对象没有属性"组">

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

我 models.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

formy.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

views.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)

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

也许你继承了AbstractUserAbstractBaseUser.

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

    from django.contrib.auth.models import PermissionMixin

你可以在这里签入 Django GitHub 代码

这是代码的一部分

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

希望解决得很好!

添加

这是我的用户模型的一部分。您应该同时继承BaseUserPermissionsMixin。然后,您可以使用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,
    )
    ...

所以你的用户模型会像...

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

希望解决得很好!