【问题标题】:Add user to permission group when creating user in Django Admin在 Django Admin 中创建用户时将用户添加到权限组
【发布时间】:2018-12-14 10:47:34
【问题描述】:

我会在创建用户时自动将用户添加到权限组。我听说过 user.groups.add(group) 和 group.user_set.add(user)。但它不起作用。我的最终目的是拥有 3 类用户:

  1. 超级管理员:一名超级管理员来管理网站。
  2. 管理员:用户管理员。可以管理普通用户。上传照片、添加新用户进行管理等。
  3. 普通用户:将使用应用程序的普通用户。他们没有任何权限,只登录网站,而不是adminSite。

模型.PY

from django.db import models
from django.contrib.auth.models import AbstractUser, Group
from django.db.models.signals import post_save
from django.dispatch import receiver


# Create your models here.

class MyUser(AbstractUser):
    descripcion = models.TextField(blank=True)
    telefono = models.PositiveSmallIntegerField(default=000)
    avatar = models.ImageField(upload_to='users/avatar/', blank=True)

    def __str__(self):
        return self.username


class RegularUser(MyUser):
    MyUser.is_staff = False
    MyUser.is_superuser = False

    class Meta:
        verbose_name = 'Usuario Regular'
        verbose_name_plural = 'Usuarios Regulares'


class AdminUser(MyUser):
    usuarios = models.ManyToManyField(RegularUser, help_text="Selecciona los usuarios que administra")
    MyUser.is_staff = True

    class Meta:
        verbose_name = 'Administrador'
        verbose_name_plural = 'Adminsitradores'

管理员.PY

from django.contrib import admin
from django import forms
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.contrib.auth.models import Group

from myApp.models import MyUser, RegularUser, AdminUser


# Register your models here.


class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required fields,
     plus a repeated password"""
    password1 = forms.CharField(label='Contraseña', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repita Contraseña',
                                widget=forms.PasswordInput)

    class Meta:
        model = MyUser
        fields = ('email',
                  'first_name',
                  'last_name',
                  'telefono',
                  'avatar',
                  'groups',)

    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("Las contraseñas no coinciden")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on the user
    , but replaces the password field with admin's password
    hash display field"""

    password = ReadOnlyPasswordHashField()

    class Meta:
        model = MyUser
        fields = ('username',
                  'email',
                  'password',
                  'first_name',
                  'last_name',
                  'descripcion',
                  'telefono',
                  'avatar',
                  )

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class AdminCreationForm(forms.ModelForm):
    """A form for creating new Admin users. Including all required fields,
    plus a repeated password"""
    password1 = forms.CharField(label='Contraseña', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repita Contraseña', widget=forms.PasswordInput)

    # usuarios = forms.CharField(label= 'Usuarios', widget=forms.SelectMultiple(choices=RegularUser.objects.all()))

    class Meta:
        model = AdminUser
        fields = ('username',
                  'email',
                  'password',
                  'telefono',
                  'avatar',
                  'usuarios',
                  'groups',)

    def clean_password2(self):
        # Check that the 2 password entries match
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise ValueError("Las contraseñas no coinciden")
        return password2

    # def _save_m2m(self):
    #     user = super().save(commit=False)
    #     self.instance.user_set = self.cleaned_data['user']

    def save(self, commit=True):
        # Save the commit password in hashed form
        user = super().save(commit=False)
        user.set_password(self.cleaned_data['password1'])
        # Set the current User as admin user
        user.is_staff = True

        if commit:
            user.save()
            group = Group.objects.get(name="Administradores")
            user.groups.add(group)
            # group.user_set.add(user)
            # group.save()
        return user

    @receiver(post_save, sender=AdminUser)
    def post_save_admin(sender, instance, **kwargs):
        if kwargs['created'] and instance.is_staff:
            grupo = Group.objects.get(name="Administradores")
            grupo.user_set.add(instance)


class AdminChangeForm(forms.ModelForm):
    """ A form for updating Administrators. Includes all the fields on the user
    , but replaces the password field with admin's password hash display field"""

    password = ReadOnlyPasswordHashField()

    class Meta:
        model = AdminUser
        fields = ('username',
                  'email',
                  'password',
                  'first_name',
                  'last_name',
                  'descripcion',
                  'telefono',
                  'avatar',
                  'usuarios',
                  'groups',
                  )

    def clean_password(self):
        # Regardless of what the admin provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class AdminUserAdmin(BaseUserAdmin):
    # The forms to add and change admin instances
    form = AdminChangeForm
    add_form = AdminCreationForm

    # The fields to be used in displaying the Admin model.
    # These overrides the definitions on the base AdminUserAdmin
    # that reference specific fields on auth.User
    list_display = ('username', 'email',)
    list_filter = ('last_login',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Información Personal', {'fields': ('first_name', 'last_name', 'descripcion', 'avatar', 'telefono',)}),
        ('Administración', {'fields': ('is_staff', 'usuarios','groups')}),
    )
    # add_fieldsets is not a standard Modeladmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'email', 'telefono', 'password1', 'password2', 'usuarios','groups')}
         ),
    )
    search_fields = ('username',)
    ordering = ('username',)
    filter_horizontal = ()



class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('username', 'email', 'is_staff')
    list_filter = ('is_staff',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('first_name', 'last_name', 'descripcion', 'avatar', 'telefono',)}),
        ('Permissions', {'fields': ('is_staff', 'is_superuser')}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'email', 'telefono', 'password1', 'password2',)}
         ),
    )
    search_fields = ('username',)
    ordering = ('username',)
    filter_horizontal = ()

    # Now register the new UserAdmin...


admin.site.register(MyUser, UserAdmin)

admin.site.register(AdminUser, AdminUserAdmin)


# @admin.register(MyUser)
# class MyUserAdmin(admin.ModelAdmin):
#     pass


# @admin.register(AdminUser)
# class AdminUserAdmin(admin.ModelAdmin):
#     # The forms to add and change Admin instances:
#     form = AdminChangeForm


@admin.register(RegularUser)
class RegularUserAdmin(admin.ModelAdmin):
    pass

我认为解决方案一定在这里,但它不起作用:

保存用户功能

def save(self, commit=True):
        # Save the commit password in hashed form
        user = super().save(commit=False)
        user.set_password(self.cleaned_data['password1'])
        # Set the current User as admin user
        user.is_staff = True

        if commit:
            user.save()
            group = Group.objects.get(name="Administradores")
            user.groups.add(group)
            # group.user_set.add(user)
            # group.save()
        return user

【问题讨论】:

    标签: python django django-admin django-users


    【解决方案1】:

    这是因为 django admin 没有使用 commit=True 调用表单的 save 方法。

    如果您真的希望仅对从管理员保存的用户执行此操作,那么您应该覆盖 ModelAdmin 上的 save_model method。这意味着您需要从django.contrib.admin 注销UserModelAdmin 并创建自己的UserModelAdmin

    如果您希望在您的应用程序中全局执行此操作,请查看post_save signal

    【讨论】:

    • 这个 UserModelAdmin 应该在 admin.py 中?那么 AdminUserAdmin(BaseUserAdmin) 类呢:。这是 UserModelAdmin 的覆盖。我需要把 save_model 方法放在这里吗?
    • 是的,任何ModelAdmin 子类都应该在admin.py 中才能被自动发现。 save_modelModelAdmin 上的一个方法,所以是的,它应该在那个类上。
    • 我在 AdminCreationForm 的保存方法上方添加 post_save 信号,并在创建 admin.site.register(AdminUser, AdminUserAdmin) 时覆盖 ModelAdmin 类。它仍然无法正常工作。请帮忙
    • @tonydelalg 请阅读有关注册信号的文档。
    【解决方案2】:

    这是我找到的解决方案。

    @receiver(post_save, sender= AdminUser)
    def add_admin_permission(sender, instance, created, **kwargs):
        if created:
            grupo = Group.objects.get(id=1)
            grupo.user_set.add(instance)
    

    【讨论】:

      猜你喜欢
      • 2014-10-21
      • 2011-03-07
      • 1970-01-01
      • 2015-02-21
      • 2019-01-04
      • 2015-12-24
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      相关资源
      最近更新 更多