且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Django中查看权限

更新时间:2023-12-01 13:42:28

Django 2.1在默认权限中添加了查看权限.以下解决方案可以在Django的早期版本中使用. https://docs.djangoproject.com/zh/2.1 /releases/2.1/#model-view-permission

Django 2.1 added a view permission to the default permissions. The solution below may work in earlier versions of Django. https://docs.djangoproject.com/en/2.1/releases/2.1/#model-view-permission

这是在Django 1.6.2中测试过的有效解决方案

This is a working solution tested in Django 1.6.2

[X] 1. Added 'view' to default permission list:确定
[X] 2. Test the 'view' permission is added to all models:确定

[X] 1. Added 'view' to default permission list: OK
[X] 2. Test the 'view' permission is added to all models: OK

[X] 3. Add "get_view_permission" to default model class.不再有用:

def get_add_permission(self):
    """
    This method has been deprecated in favor of
    `django.contrib.auth.get_permission_codename`. refs #20642
    """
    warnings.warn(
        "`Options.get_add_permission` has been deprecated in favor "
        "of `django.contrib.auth.get_permission_codename`.",
        PendingDeprecationWarning, stacklevel=2)
    return 'add_%s' % self.model_name

所有这些方法get_foo_permission

[X] 4. Add "has_view_permission" to default admin class应该是:

def has_view_permission(self, request, obj=None):
    """
    Returns True if the given request has permission to change or view
    the given Django model instance.


    If obj is None, this should return True if the given request has
    permission to change *any* object of the given type.
    """
    opts = self.opts
    codename = get_permission_codename('view', opts)
    return self.has_change_permission(request, obj) or \
        request.user.has_perm("%s.%s" % (opts.app_label, codename))

如果模型是内联模型,请检查其正确性,因此需要注意正确的视图

if the model is an inline one check its right, so need to be aware of the right view

def get_inline_instances(self, request, obj=None):

    ...

    if not (inline.has_add_permission(request) or
            inline.has_change_permission(request, obj) or
            inline.has_delete_permission(request, obj) or
            inline.has_view_permission(request, obj)):  # add the view right
        continue

    ...

get_model_perms上进行修改以包含视图",以相同的想法执行此操作:

Do the modification on get_model_perms to include 'view', in the same idea do this one:

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):

    ...

    context.update({

        ...

        'has_view_permission': self.has_view_permission(request, obj), # add the view right

        ...

    })

    ....

允许右视图"呈现一个对象的页面,并禁用右视图"以保存在页面上所做的修改,以避免[X] 8. Modify "view" permission to make form read only

Allow the 'right view' to render the page (of one object) and disable the 'right view' to save the modification done on a page avoid [X] 8. Modify "view" permission to make form read only

@csrf_protect_m
@transaction.atomic
def change_view(self, request, object_id, form_url='', extra_context=None):
    "The 'change' admin view for this model."
    model = self.model
    opts = model._meta

    obj = self.get_object(request, unquote(object_id))

    # addthe view right
    if not (self.has_view_permission(request, obj) or
            self.has_change_permission(request, obj)):
        raise PermissionDenied

    ...

    inline_instances = self.get_inline_instances(request, obj)
    # do not save the change if I'm not allowed to:
    if request.method == 'POST' and self.has_change_permission(request, obj):
        form = ModelForm(request.POST, request.FILES, instance=obj)

    ...

允许右视图"呈现页面(所有对象的列表)

Allow the 'right view' to render the page (the list of all objects)

@csrf_protect_m
def changelist_view(self, request, extra_context=None):
    """
    The 'change list' admin view for this model.
    """
    from django.contrib.admin.views.main import ERROR_FLAG
    opts = self.model._meta
    app_label = opts.app_label
    # allow user with the view right to see the page
    if not (self.has_view_permission(request, None) or
            self.has_change_permission(request, None)):
        raise PermissionDenied

    ....

[X] 5. Update default template to list models if user has view permission:可以,但是要避免修改html模板,请编辑此文件:contrib/admin/site.py

[X] 5. Update default template to list models if user has view permission: OK but to avoid to modify the html template edit this file: contrib/admin/site.py

class AdminSite(object):

    @never_cache
    def index(self, request, extra_context=None):

        ...

        # add the view right
        if perms.get('view', False) or perms.get('change', False):
        try:
            model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
        except NoReverseMatch:
            pass

        ...

    def app_index(self, request, app_label, extra_context=None):

        ...

        # add the view right
        if perms.get('view', False) or perms.get('change', False):
            try:
                model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
            except NoReverseMatch:
                pass

        ...

[X] 6. Confirm user can "view" but not "change" the model[X] 7. Remove "Save and Add another" button if user is viewing an item:应该可以,但我做到了:

[X] 6. Confirm user can "view" but not "change" the model and [X] 7. Remove "Save and Add another" button if user is viewing an item: should be ok but i did that:

'show_save_as_new': context['has_add_permission'] and not is_popup and change and save_as,
'show_save': context['has_change_permission'],

[X] 8.修改查看"权限以使表单只读:好的,但是我有上面提到的其他解决方案

[X] 8. Modify "view" permission to make form read only: Ok but i have an other solution see above