Login
网站首页 > 文章中心 > 其它

使用django-guardian实现django-admin的行级权限控制的方法

作者:小编 更新时间:2023-10-09 10:06:47 浏览量:181人看过

下面是使用django-guardian实现django-admin的行级权限控制的方法的完整攻略.

django-guardian是一个用于Django的第三方插件,它提供一种简单的方式来将对象级别的访问控制系统嵌入到你的应用程序中.

您可以使用pip安装django-guardian:


pip install django-guardian


然后将guardian添加到INSTALLED_APPS中:


INSTALLED_APPS = [
# ...
'guardian',
# ...
]


并且在MIDDLEWARE中添加GuardianMiddleware:


MIDDLEWARE = [
# ...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'guardian.middleware.GuardianMiddleware',
# ...
]


最后,在settings.py文件中添加以下设置:


AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'guardian.backends.ObjectPermissionBackend',
]


创建一个模型后台(ModelAdmin)是创建一个新的admin后台的第一步,这为您提供了一个管理特定模型的界面. 您可以针对不同的模型创建几个后台界面.



需要创建一个自定义的admin后台,即一个子类GuardedModelAdmin(位于guardian.admin中),并将其传递给模型注册装饰器:



现在,我们将为创建的文章添加用户级别的权限控制:

①首先,在models.py中,定义一个组:


from django.contrib.auth.models import Group

class Writer(Group):

class Meta:
    verbose_name = "Writer"
    verbose_name_plural = "Writers"



from django.db import models
from django.conf import settings
from django.urls import reverse
from guardian.shortcuts import assign_perm

class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

def __str__(self):
    return self.title

def get_absolute_url(self):
    return reverse('post_detail', args=[str(self.id)])

class Writer(Group):

class Meta:
    verbose_name = "Writer"
    verbose_name_plural = "Writers"

# 在Post模型类中添加如下代码
class Meta:
permissions = (("can_view_post", "Can view post"),)

assign_perm("can_view_post", Writer.objects.get_or_create(name="nobody")[0])



# 在admin.py中的PostModelAdmin类中添加如下代码
from django.contrib.auth.models import Group
from django.forms import CheckboxSelectMultiple
from guardian.admin import GuardedModelAdmin

class GroupAdminForm(forms.ModelForm):
class Meta:
    model = Group
    fields = '__all__'
    widgets = {
        'permissions': CheckboxSelectMultiple,
    }

permissions = forms.MultipleChoiceField(
    choices=[],
    widget=CheckboxSelectMultiple,
    help_text=_('Permissions of the group')
)

def __init__(self, *args, **kwargs):
    super(GroupAdminForm, self).__init__(*args, **kwargs)

    choices = [(x.id, x.name) for x in Permission.objects.all().order_by('content_type__app_label', 'content_type__model', 'codename')]
    self.fields['permissions'].choices = choices

def save(self, commit=True):
    group = super(GroupAdminForm, self).save(commit)

    if commit:
        perms = self.cleaned_data.get('permissions', [])
        permissions = Permission.objects.filter(pk__in=perms)
        group.permissions.set(permissions)

    return group

@admin.register(Writer)
class WriterAdmin(GuardedModelAdmin):
form = GroupAdminForm



# 在admin.py中的GroupAdminForm类中添加如下代码
from django.contrib.auth.models import Permission

class PermissionFilter(SimpleListFilter):
title = _('permissions')
parameter_name = 'permissions'

def lookups(self, request, model_admin):
    perms = Permission.objects.all().order_by('content_type__app_label', 'content_type__model', 'codename')
    choices = []
    for perm in perms:
        content_type = perm.content_type
        choice = (f'{content_type.app_label}.{content_type.model}.{perm.codename}', perm.name)
        if choice not in choices:
            choices.append(choice)
    return choices

def queryset(self, request, queryset):
    if self.value():
        content_type, codename = self.value().rsplit('.', 1)
        queryset = queryset.filter(
            permissions__content_type__app_label=content_type,
            permissions__content_type__model=content_type,
            permissions__codename=codename
        )
    return queryset






Hello

World

Today

首先,我们需要在models.py中为标题创建一个单独的模型,并将其与文章关联:


from django.db import models
from django.conf import settings
from django.urls import reverse

class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

def __str__(self):
    return self.title

def get_absolute_url(self):
    return reverse('post_detail', args=[str(self.id)])

class PostTitle(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='titles')
title = models.CharField(max_length=255)

def __str__(self):
    return self.title

class Meta:
    verbose_name = "Post Title"
    verbose_name_plural = "Post Titles"



[, , ]



from django.contrib.auth.models import User
from guardian.shortcuts import assign_perm

post = Post()
post.save()

titles = ['Hello', 'World', 'Today']
for title in titles:
PostTitle.objects.create(post=post, title=title)

alice = User.objects.create(username='alice')
bob = User.objects.create(username='bob')

assign_perm('view_posttitle', alice, post.titles.all()[0])
for title in post.titles.all():
assign_perm('view_posttitle', bob, title)


这将导致以下授权:

Bob可以查看所有标题,而Alice不能.

现在,我们将修改PostTitleModelAdmin以隐藏每个区域的权限和添加我们的自定义列表视图:



创建我们的自定义模板(view_title.html)以允许我们仅显示每个标题的一部分:


{% extends "admin/base_site.html" %}

{% block content_title %}
{{ object.title|safe }}
{% endblock %}

{% block content %}
{% for title in object.post.titles.all %}
    {% if title|has_perm:'view_posttitle' %}
        

{{ title.title|safe }}

{% endif %} {% endfor %} {% endblock %}

现在,当我们单击每个标题时,我们将只能看到我们已授权的部分.

详细的攻略就是这样了,希望能对你有所帮助.

以上就是土嘎嘎小编为大家整理的使用django-guardian实现django-admin的行级权限控制的方法相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章