如果只给用户提供自定义视图权限,如何让用户查看django管理主页?

时间:2016-12-07 18:27:28

标签: django django-admin django-permissions

通过在我的某个模型中添加以下代码,我可以为模型添加查看权限。

class Meta:
    default_permissions = ('add', 'change', 'delete', 'view')

我在django-admin中创建了一个用户,并且只授予了查看权限。我希望用户应该只能查看此特定模型的值。

但是在与用户登录后,我收到一条错误,即用户没有编辑任何内容的权限。(请参阅屏幕截图)。

我是否可以通过仅授予VIEW权限来允许用户查看特定模型?任何帮助将不胜感激。

enter image description here

1 个答案:

答案 0 :(得分:1)

这涉及到相当麻烦。我将在下面提出一些想法。

首先,让我们在admin中显示一个view预先准备的模型:

from django.contrib import admin
from django.contrib.auth import get_permission_codename

from .models import MyModel


@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):

    def get_model_perms(self, request):
        model_perms = super(MyModelAdmin, self).get_model_perms(request)

        view_perm = self.has_view_permission(request)

        model_perms.update({
            'change': view_perm,
            'view': view_perm,
        })

    def has_view_permission(self, request):
        opts = self.opts
        codename = get_permission_codename('view', opts)
        return request.user.has_perm("%s.%s" % (opts.app_label, codename))

注意:我在changelist_view()挂钩。我发现它更容易。

其次,我们将viewlist_view()view_view()两个观点添加到MyModelAdmin

def get_urls(self):
    from django.conf.urls import url

    def wrap(view):
        def wrapper(*args, **kwargs):
            return self.admin_site.admin_view(view)(*args, **kwargs)
        wrapper.model_admin = self
        return update_wrapper(wrapper, view)

    info = self.model._meta.app_label, self.model._meta.model_name

    urlpatterns = super(MyModelAdmin, self).get_urls()
    urls = [
        url(r'^viewlist/$', wrap(self.viewlist_view), name='%s_%s_viewlist' % info),
        url(r'^(.+)/view/$', wrap(self.view_view), name='%s_%s_view' % info),
    ]

    return urls + urlpatterns

@csrf_protect_m
def viewlist_view(self, request, extra_context=None):
    opts = self.model._meta
    app_label = opts.app_label
    if not self.has_view_permission(request):
        raise PermissionDenied

    context = dict(
        self.admin_site.each_context(request),
        title='%s view list' % force_text(opts.verbose_name),
        queryset=self.get_queryset(request),
    )
    context.update(extra_context or {})

    return TemplateResponse(request, 'admin/view_list.html', context)

@csrf_protect_m
def view_view(self, request, object_id, extra_context=None):
    opts = self.model._meta
    app_label = opts.app_label
    if not self.has_view_permission(request):
        raise PermissionDenied

    context = dict(
        self.admin_site.each_context(request),
        object_id=object_id,
    )

    return TemplateResponse(request, 'admin/view_view.html', context)

第三,勾选changelist_view()

@csrf_protect_m
def changelist_view(self, request, extra_context=None):
    if not self.has_change_permission(request, None):
        # or redirect
        return self.viewlist_view(request, extra_context)
    return super(MyModelAdmin, self).changelist_view(request, extra_context)

第四,添加两个模板:

admin/view_list.html

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

{% block content %}
<div id="content-main">
  <ul>
    {% for obj in queryset %}
      <li><a href="{{ obj.get_admin_view_url }}">{{ obj }}</a></li>
    {% endfor %}
  </ul>
</div>
{% endblock %}

admin/view_view.html

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

{% block content %}
<div id="content-main">

{{ object_id }}

</div>
{% endblock %}

最后,我在get_admin_view_url()添加了MyModel方法,以进入管理视图:

from __future__ import unicode_literals

from django.db import models
from django.core.urlresolvers import reverse


class MyModel(models.Model):
    name = models.CharField(max_length=255)

    class Meta:
        default_permissions = ('add', 'change', 'delete', 'view')

    def __unicode__(self):
        return self.name

    def get_admin_view_url(self):
        info = (self._meta.app_label, self._meta.model_name)
        return reverse('admin:%s_%s_view' % info, args=(self.id,))

我希望这是有道理的。