Skip to main content
 首页 » 编程设计

python之Django之能够在管理控制台中为自定义用户模型分配权限和组

2025年05月04日23shihaiming

我刚刚在 django 中创建了一个名为 Subscriber 的自定义用户模型,它继承自 AbstractBaseUser 和 PermissionsMixin。然后,我在我的 admin.py 文件中对必要的表单类进行了子类化,以便在管理控制台中注册我的自定义用户模型。

首先,我对自定义用户模型以及权限和组如何在 Django 中组合在一起感到有点困惑。在将 PermissionsMixin 传递给我的用户模型后,我运行了 manage.py migrate 脚本,它在我的数据库 subscriber_conf_subscriber_groups 和 subscriber_conf_subscriber_user_permissions 中创建了两个新表。此外,在 django documentation 内给出了一个 Group 模型从管理员注销的示例,所以我也这样做了。

现在在管理控制台中,我只有一个订阅者列表和用于创建和编辑订阅者的表单。我的问题是,如何添加从管理控制台向订阅者分配权限和组的功能?此时新用户模型是否仍与内置的 django 权限和组关联,或者这是我必须编写的代码?

任何澄清都会很好。

模型.py

from django.db import models 
from django.contrib.auth.models import User 
from django.conf import settings 
from django.utils import timezone 
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin 
 
#Custom user manager 
class SubscriberManager(BaseUserManager): 
 
 
    def create_user(self, email, first_name, last_name, dti_id, street_address1,  
        street_address2, city, state, full_zip, phone_number, password=None): 
 
        #save 5 digit zip 
        tmp_zip = full_zip.split("-") 
        new_zip = tmp_zip[0] 
 
        return self._create_user(email, first_name, last_name, dti_id, street_address1,  
            street_address2, city, state, new_zip, full_zip, phone_number,  
            False, False, password, 0) 
 
    #utility function 
    def _create_user(self, email, first_name, last_name, dti_id, street_address1, 
        street_address2, city, state, zip_code, full_zip, 
        phone_number, is_superuser, is_staff, password=None, account_updated=0): 
 
        #define now 
        now = timezone.now() 
 
        if not email: 
            raise ValueError('Users must have an email address') 
 
        #use django to normalize the email address 
        email = self.normalize_email(email) 
 
        user = self.model( 
            email = email, 
            first_name = first_name, 
            last_name = last_name, 
            dti_id = dti_id, 
            street_address1 = street_address1, 
            street_address2 = street_address2, 
            city = city, 
            state = state, 
            zip_code = zip_code, 
            full_zip = full_zip, 
            phone_number = phone_number, 
            account_updated = account_updated, 
            is_admin = is_staff,  
            is_active = True, 
            is_superuser = is_superuser, 
            date_joined = now,  
            last_modified = now) 
        user.set_password(password) 
        user.save(using=self._db) 
 
        return user 
 
    #create superuser override 
    def create_superuser(self, email, first_name, last_name, dti_id, street_address1, 
        street_address2, city, state, full_zip, phone_number, password): 
 
        #either need to create needed fields or require them in user model 
 
        tmp_zip = full_zip.split("-") 
        new_zip = tmp_zip[0] 
 
        return self._create_user(email, first_name, last_name, dti_id, street_address1,  
            street_address2, city, state, new_zip, full_zip, phone_number,  
            True, True, password, 0) 
 
 
#Custom user definition 
class Subscriber(AbstractBaseUser, PermissionsMixin): 
    email = models.EmailField(max_length=254, unique=True, db_index=True) 
    first_name = models.CharField(max_length=100) 
    last_name = models.CharField(max_length=100) 
    dti_id = models.IntegerField(default=0) 
    street_address1 = models.CharField(max_length=100) 
    street_address2 = models.CharField(max_length=100, blank=True) 
    city = models.CharField(max_length=100) 
    state = models.CharField(max_length=10) 
    zip_code = models.CharField(max_length=5) 
    full_zip = models.CharField(max_length=10, blank=True) 
    account_updated = models.BooleanField(default=0) 
    phone_number = models.CharField(max_length=20) 
 
    last_modified = models.DateTimeField(default=timezone.now) 
    date_joined = models.DateTimeField(default=timezone.now) 
    is_active = models.BooleanField(default=True) 
    is_admin = models.BooleanField(default=False) 
 
    objects = SubscriberManager() 
 
    USERNAME_FIELD = 'email' 
 
    REQUIRED_FIELDS = [ 
        'first_name',  
        'last_name',  
        'dti_id',  
        'street_address1', 
        'street_address2', 
        'city', 
        'state', 
        'full_zip', 
        'phone_number', 
    ] 
 
    # define custom perms 
    class Meta: 
        permissions = ( 
            ("view_web", "Can access SJ web content"), 
            ("view_web_e_edition", "Can access SJ e-edition content"), 
            ("view_wweb", "Can access weekly web content"), 
            ("view_wweb_e_edition", "Can access weekly e-edition content"), 
 
            #.... more permissions 
            #may be able to use this for subscriber coupons and such 
        ) 
 
    def get_full_name(self): 
        return self.email 
 
    def get_short_name(self): 
        return self.email 
 
    def __unicode__(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.is_admin 

admin.py

from django import forms 
from django.contrib import admin 
from django.contrib.auth.models import Group 
from django.contrib.auth.admin import UserAdmin 
from django.contrib.auth.forms import ReadOnlyPasswordHashField 
 
from subscriber_conf.models import Subscriber 
 
 
class SubscriberCreationForm(forms.ModelForm): 
 
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput) 
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) 
 
    class Meta: 
        model = Subscriber 
        fields = ( 
            'email',  
            'first_name', 
            'last_name', 
            'dti_id', 
            'street_address1', 
            'street_address2', 
            'city', 
            'state', 
            'zip_code', 
            'full_zip', 
            'phone_number', 
        ) 
 
    def clean_password2(self): 
        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): 
        user = super(SubscriberCreationForm, self).save(commit=False) 
        user.set_password(self.cleaned_data["password1"]) 
 
        #perhaps do some stuff with times and dates 
 
        if commit: 
            user.save() 
        return user 
 
 
class SubscriberChangeForm(forms.ModelForm): 
    password = ReadOnlyPasswordHashField() 
 
    class Meta: 
        model = Subscriber 
        fields = ( 
            'email', 
            'password', 
            'first_name', 
            'last_name', 
            'dti_id', 
            'street_address1', 
            'street_address2', 
            'city', 
            'state', 
            'zip_code', 
            'full_zip', 
            'phone_number', 
            'account_updated', 
            'is_admin',  
            'is_active', 
            'is_superuser', 
            'date_joined',  
            'last_modified' 
            ) 
 
    def clean_password(self): 
        return self.initial["password"] 
 
 
class SubscriberAdmin(UserAdmin): 
    form = SubscriberChangeForm 
    add_form = SubscriberCreationForm 
 
    date_hierarchy = 'last_modified' 
 
 
    list_display = ('email', 'first_name', 'last_name', 
    'street_address1', 'street_address2', 'city', 'state', 
    'zip_code', 'full_zip', 'phone_number', 'dti_id', 'account_updated', 
    'last_modified', 'is_admin', 'is_superuser') 
    list_filter = ('is_admin', 'is_superuser', 'account_updated',) 
    fieldsets = ( 
        (None, {'fields': ('email', 'password')}), 
        ('Personal info', {'fields': ('first_name', 'last_name', 'street_address1',  
            'street_address2', 'city', 'state', 'zip_code', 'full_zip', 
            'phone_number', 'account_updated',)}), 
        ('Permissions', {'fields': ('is_admin',)}), 
    ) 
 
    add_fieldsets = ( 
        (None, { 
            'classes': ('wide',), 
            'fields': ('email', 'first_name', 'last_name', 'street_address1', 'street_address2', 
            'city', 'state', 'full_zip', 'phone_number', 'password1', 'password2')} 
        ), 
    ) 
    search_fields = ('email', 'street_address1', 'street_address2', 'first_name', 
        'last_name',) 
    ordering = ('dti_id',) 
    filter_horizontal = () 
 
 
admin.site.register(Subscriber, SubscriberAdmin) 
admin.site.unregister(Group) 

请您参考如下方法:

有点晚了,但对于其他人,试试这个

 #admin.site.unregister(Group) <-- comment this line 

在字段集中

('Permissions', {'fields': ('is_admin','is_staff','groups',)}) 

使用第一个,您可以从管理员管理组,使用第二个,您可以将组分配给新用户。我希望这有帮助! 问候!