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

时间:2014-12-03 18:57:42

标签: python django django-admin django-users django-permissions

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

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

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

任何澄清都会很棒。

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

My django admin console

2 个答案:

答案 0 :(得分:0)

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

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

和in fieldsets

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

第一个可以管理来自Admin的组,第二个可以将组分配给新用户。我希望这有帮助! 问候!

答案 1 :(得分:-1)

在SubscriberAdmin类中,更改field_sets和add_fieldsets,如下所示。在权限中包含组。

    fieldsets = (
    (None, {'fields': ('name', 'password')}),
    ('Personal info', {'fields': ('email', 'phone', 'civilId', 'address',)}),
    ('Permissions', {'fields': ('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': ('name', 'email', 'password1', 'password2', 'phone', 
            'civilId', 'address', 'groups',)}
    ),
    ('Permissions', {'fields': ('groups',)}),
)

在权限中包含组。还有一件事,如果你使用组,为什么取消注册组