在 Django 中查看权限 [英] View permissions in Django

查看:49
本文介绍了在 Django 中查看权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于 django admin 在它的 auth 中有三个权限:添加、更改、删​​除!我想在管理面板的此身份验证中添加查看权限.我知道我必须自定义权限才能在身份验证|权限|可以查看权限"中添加查看权限才能查看所有条目!

方法:

[X] 1. 默认权限列表中添加查看"

#./contrib/auth/management/init.pydef _get_all_permissions(opts):返回给定选项中所有权限的(代号、名称)."烫发 = []对于 ('add', 'change', 'delete', 'view') 中的操作:perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))返回权限 + 列表(opts.permissions)

[X] 2. 测试'view'权限是否添加到所有模型

运行 manage.py syncdb

我确认现在为 auth_permissions 表中的所有表添加了查看权限

[X] 3. 为默认模型类添加get_view_permission".

在模型类中添加了 get_view_permission.您可以在文件 ./db/models/options.py 中找到它,这是下一步 admin 类使用的.

def get_view_permission(self):返回 '​​view_%s' % self.object_name.lower()

[X] 4. 添加has_view_permission"到默认管理类

为了保持一致,我将向系统添加has_view_permission".看起来它应该在 contrib/admin/options.py 中的某个地方.确保如果用户有更改权限,则自动隐含查看权限.

#/contrib/admin/options.py# 添加了 has_view_permissionsdef has_view_permission(self, request, obj=None):"""如果给定的请求有权更改或查看,则返回 True给定的 Django 模型实例.如果 obj 是 None,如果给定的请求有,这应该返回 True更改给定类型的*任何*对象的权限."""opts = self.opts返回 self.has_change_permission(request, obj) 或 
equest.user.has_perm(opts.app_label + '.' + opts.get_view_permission())# 修改了 get_model_perms 以包含视图".# 不知道这可以用在哪里,但尽量保持一致def get_model_perms(self, request):"""返回此模型的所有烫发的字典.这个字典有钥匙添加、更改和删除以及查看对 True/False 的映射对于这些操作中的每一个."""返回 {添加":self.has_add_permission(请求),'改变':self.has_change_permission(请求),'删除':self.has_delete_permission(请求),视图":self.has_view_permission(请求),}# 修改 response_add 函数,将用户返回到模式列表# 如果他们添加了一个单位并且有查看权限...别的:self.message_user(请求,味精)# 找出重定向的位置.如果用户有更改权限,# 重定向到此对象的更改列表页面.否则,# 重定向到管理索引.#if self.has_change_permission(request, None):如果 self.has_change_permission(request, None) 或 self.has_view_permission(request, None):post_url = '../'别的:post_url = '../../../'返回 HttpResponseRedirect(post_url)# 修改了change_view 函数,使其成为详细信息# 有查看权限的用户#如果不是 self.has_change_permission(request, obj):如果不是 (self.has_change_permission(request, obj) 或 (self.has_view_permission(request, obj) 而不是 request.POST)):提高权限被拒绝# 修改了changelist_view 函数,使其显示项目列表# 如果你有查看权限def changelist_view(self, request, extra_context=None):此模型的‘更改列表’管理视图."从 django.contrib.admin.views.main 导入更改列表,ERROR_FLAGopts = self.model._metaapp_label = opts.app_label#如果不是 self.has_change_permission(request, None):如果不是(self.has_change_permission(request, None) 或 self.has_view_permission(request, None)):提高权限被拒绝

[X] 5. 如果用户有查看权限,更新默认模板以列出模型

我修改了 contrib/admin/templates/admin/index.html 中的默认模板.这也可以通过将文件复制到本地模板目录来处理.我对两者都进行了更改,因此如果以后的升级覆盖了我的更改,我会有一份副本.

{% for model in app.models %}<tr>{% if model.perms.change %}<th scope="row"><a href="{{model.admin_url }}">{{model.name}}</a></th>{% 别的 %}{% if model.perms.view %}<th scope="row"><a href="{{model.admin_url }}">{{model.name}}</a></th>{% 别的 %}<th scope="row">{{model.name }}</th>{% 万一 %}{% 万一 %}

[X] 6. 确认用户可以查看"但不能更改"模型

发现 contrib/admin/templatetags/admin_modify.py 似乎控制保存/保存和继续按钮的出现与否.将保存"字段从默认的始终为 True 更改为检查上下文和权限.如果用户有更改或添加权限,他们应该能够保存.

'show_save': (change and context['has_change_permission']) or (context['add'] and context['has_add_permission'])

[X] 7. 如果用户正在查看一个项目,删除保存并添加另一个"按钮

再次修改 contrib/admin/templatetags/admin_modify.py.我不知道save_as"是什么意思,所以也许我弄坏了一些东西,但它似乎有效.

#'show_save_and_add_another':上下文['has_add_permission'] 和# not is_popup and (not save_as or context['add']) ,'show_save_and_add_another':不是 is_popup 和((更改和上下文['has_change_permission'])或(上下文['add']和上下文['has_add_permission']))和(不是 save_as 或 context['add']),

[X] 8.修改查看"权限,使表单只读

如果用户有查看"权限和更改"权限,则什么都不做.更改覆盖视图.

如果用户拥有查看"权限而没有更改",则更改默认表单并向表单元素添加禁用或只读属性.并非所有浏览器都支持这一点,但出于我的目的,我可以要求用户使用正确的浏览器.[禁用/只读示例][1]

发现并非所有浏览器都支持只读",因此它将某些控件设置为只读,而将其他控件设置为禁用.这允许用户在需要时从文本控件复制数据.

#/django/contrib/admin/templates/admin/change_form.html{# 用于预填充字段的 JavaScript #}{% prepopulated_fields_js %}

</form></div>{% 如果 has_view_permission 而不是 has_change_permission %}<script type="text/javascript">jQuery('input:text').attr('readonly', 'readonly');jQuery('textarea').attr('readonly', 'readonly');jQuery('input:checkbox').attr('disabled', true);jQuery('select').attr('disabled', true);jQuery('.add-another').hide();{% 万一 %}

答案来源:我该怎么办修改 django 以创建视图"许可?

问题:按照上面的回答后,我已经完成并且可以看到这个 127.0.0.1:8000/en-us/admin/页面为只读 **但用户中的用户不可见 127.0.0.1:8000/en-us/admin/user.需要帮助!**

解决方案

Django 2.1 添加了默认权限的查看权限.下面的解决方案可能适用于早期版本的 Django.https://docs.djangoproject.com/en/2.1/release/2.1/#model-view-permission

<小时>

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

[X] 1. 将查看"添加到默认权限列表:OK
[X] 2. 测试所有模型都添加了'view'权限:OK

[X] 3. 将get_view_permission"添加到默认模型类中. 不再有用:

def get_add_permission(self):"""该方法已被弃用`django.contrib.auth.get_permission_codename`.参考文献 #20642"""警告.警告(`Options.get_add_permission` 已被弃用"`django.contrib.auth.get_permission_codename`.",PendingDeprecationWarning, stacklevel=2)返回 '​​add_%s' % self.model_name

所有这些方法都是如此get_foo_permission

[X] 4. 添加has_view_permission"到默认管理类应该是:

def has_view_permission(self, request, obj=None):"""如果给定的请求有权更改或查看,则返回 True给定的 Django 模型实例.如果 obj 是 None,如果给定的请求有,这应该返回 True更改给定类型的*任何*对象的权限."""opts = self.opts代号 = get_permission_codename('view', opts)返回 self.has_change_permission(request, obj) 或 
equest.user.has_perm("%s.%s" % (opts.app_label, codename))

如果模型是内联的,检查它的正确性,所以需要注意正确的视图

def get_inline_instances(self, request, obj=None):...如果不是 (inline.has_add_permission(request) 或inline.has_change_permission(request, obj) 或inline.has_delete_permission(request, obj) 或inline.has_view_permission(request, obj)): # 添加视图权限继续...

get_model_perms 进行修改以包含 'view',以同样的想法做这个:

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):...上下文.更新({...'has_view_permission': self.has_view_permission(request, obj), # 添加视图权限...})....

允许'右视图'渲染页面(一个对象)并禁用'右视图'以保存在页面上所做的修改避免[X] 8.修改视图"权限以制作表单只读

@csrf_protect_m@transaction.atomicdef change_view(self, request, object_id, form_url='', extra_context=None):此模型的‘更改’管理视图."模型 = self.modelopts = model._metaobj = self.get_object(request, unquote(object_id))# 添加视图权限如果不是 (self.has_view_permission(request, obj) 或self.has_change_permission(request, obj)):提高权限被拒绝...inline_instances = self.get_inline_instances(request, obj)# 如果我不允许,请不要保存更改:如果 request.method == 'POST' 和 self.has_change_permission(request, obj):form = ModelForm(request.POST, request.FILES, instance=obj)...

允许'右视图'渲染页面(所有对象的列表)

@csrf_protect_mdef changelist_view(self, request, extra_context=None):"""此模型的更改列表"管理视图."""从 django.contrib.admin.views.main 导入 ERROR_FLAGopts = self.model._metaapp_label = opts.app_label# 允许有查看权限的用户查看页面如果不是 (self.has_view_permission(request, None) 或self.has_change_permission(request, None)):提高权限被拒绝....

[X] 5. 如果用户有查看权限,更新默认模板以列出模型:好的,但为了避免修改 html 模板编辑这个文件:contrib/admin/site.py

class AdminSite(object):@never_cache定义索引(自我,请求,extra_context=None):...# 添加右视图如果 perms.get('view', False) 或 perms.get('change', False):尝试:model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)除了 NoReverseMatch:经过...def app_index(self, request, app_label, extra_context=None):...# 添加右视图如果 perms.get('view', False) 或 perms.get('change', False):尝试:model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)除了 NoReverseMatch:经过...

[X] 6. 确认用户可以查看"但不能更改"模型[X] 7. 如果用户正在查看模型,则删除保存并添加另一个"按钮item:应该没问题,但我做到了:

'show_save_as_new':context['has_add_permission'] 而不是 is_popup 和 change 和 save_as,'show_save':上下文['has_change_permission'],

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

As django admin has three permissions in it's auth : add, change, delete! I want to add view permission in this auth in admin panel.I know i have to customize permissions to add view permission in 'auth|permission|can view permission' to view all entries!

THE WAY:

[X] 1. Added 'view' to default permission list

#./contrib/auth/management/init.py
def _get_all_permissions(opts):

    "Returns (codename, name) for all permissions in the given opts."
    perms = []
    for action in ('add', 'change', 'delete', 'view'):

        perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))

    return perms + list(opts.permissions)

[X] 2. Test the 'view' permission is added to all models

run manage.py syncdb

I confirmed that view permission is now added for all tables in the auth_permissions table

[X] 3. Add "get_view_permission" to default model class.

Added get_view_permission to the model class. You can find this in the file ./db/models/options.py This is used by the admin class in the next step.

def get_view_permission(self):

    return 'view_%s' % self.object_name.lower()

[X] 4. Add "has_view_permission" to default admin class

Just to be consistent I'm going to add "has_view_permission" to the system. Looks like it should be somewhere in contrib/admin/options.py. Made sure if the user has has change permission, then view permissions are automatically implied.

# /contrib/admin/options.py
# Added has_view_permissions
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
    return self.has_change_permission(request, obj) or 

        request.user.has_perm(opts.app_label + '.' + opts.get_view_permission())


# modified get_model_perms to include 'view' too.
# No idea where this may be used, but trying to stay consistent
def get_model_perms(self, request):

    """
    Returns a dict of all perms for this model. This dict has the keys
    add, change, and delete and view mapping to the True/False
    for each of those actions.
    """
    return {

        'add': self.has_add_permission(request),
        'change': self.has_change_permission(request),
        'delete': self.has_delete_permission(request),
        'view': self.has_view_permission(request),

    }


# modified response_add function to return the user to the mode list
# if they added a unit and have view rights
...

    else:

        self.message_user(request, msg)

        # Figure out where to redirect. If the user has change permission,
        # redirect to the change-list page for this object. Otherwise,
        # redirect to the admin index.
        #if self.has_change_permission(request, None):
        if self.has_change_permission(request, None) or self.has_view_permission(request, None):

            post_url = '../'

        else:

            post_url = '../../../'

        return HttpResponseRedirect(post_url)

    # modified the change_view function so it becomes the details
    # for users with view permission

        #if not self.has_change_permission(request, obj):
        if not (self.has_change_permission(request, obj) or (self.has_view_permission(request, obj) and not request.POST)):

            raise PermissionDenied

        # modified the changelist_view function so it shows the list of items
        # if you have view permissions

def changelist_view(self, request, extra_context=None):

            "The 'change list' admin view for this model."
            from django.contrib.admin.views.main import ChangeList, ERROR_FLAG
            opts = self.model._meta
            app_label = opts.app_label
            #if not self.has_change_permission(request, None):
            if not (self.has_change_permission(request, None) or self.has_view_permission(request, None)):

                raise PermissionDenied

[X] 5. Update default template to list models if user has view permission

I modified the default template in contrib/admin/templates/admin/index.html. This could also be handled by copying the file to the local templates directory instead. I made changes in both so I have a copy if a later upgrade overwrites my changes.

{% for model in app.models %}

    <tr>
    {% if model.perms.change %}

        <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>

    {% else %}

        {% if model.perms.view %}

            <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>

        {% else %}

            <th scope="row">{{ model.name }}</th>

        {% endif %}

    {% endif %}

[X] 6. Confirm user can "view" but not "change" the model

Found contrib/admin/templatetags/admin_modify.py appears to control save / save and continue buttons appearing or not. Changed "save" field from default of always True, to check for context and permissions. User should be able to save if they have change or add permissions.

'show_save': (change and context['has_change_permission']) or (context['add'] and context['has_add_permission'])

[X] 7. Remove "Save and Add another" button if user is viewing an item

Modified contrib/admin/templatetags/admin_modify.py again. I don't know what 'save_as' means so maybe I broke something, but it seems to work.

#'show_save_and_add_another': context['has_add_permission'] and
# not is_popup and (not save_as or context['add']) ,
'show_save_and_add_another': not is_popup and
    (( change and context['has_change_permission']) or (context['add'] and context['has_add_permission']))
    and
    (not save_as or context['add']),

[X] 8. Modify "view" permission to make form read only

If the user has "view" permission and "change" permission, then do nothing. Change overrides view.

If the user has "view" permission without "change" then change the default forms and add DISABLED or READONLY attributes to the form elements. Not all browsers support this, but for my purposes I can require that users use the right one. [Disabled / Readonly example][1]

Found that not all browsers honor "readonly" so it sets some controls to readonly, others to disabled. This allows users to copy data from the text controls if needed.

#/django/contrib/admin/templates/admin/change_form.html


{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}


</div>
</form></div>
{% if has_view_permission and not has_change_permission %}

    <script type="text/javascript">
    jQuery('input:text').attr('readonly', 'readonly');
    jQuery('textarea').attr('readonly', 'readonly');
    jQuery('input:checkbox').attr('disabled', true);
    jQuery('select').attr('disabled', true);
    jQuery('.add-another').hide();
    </script>

{% endif %}

ANSWER SOURCE : ​How can I MODIFY django to create "view" permission?

Question: After following above answer i have done and can see this 127.0.0.1:8000/en-us/admin/ page as read-only **but the users in users is not visible 127.0.0.1:8000/en-us/admin/user . Need help!**

解决方案

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


This is a working solution tested in Django 1.6.2

[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. is useless any more:

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

And that the case for all of those methods get_foo_permission

[X] 4. Add "has_view_permission" to default admin class should be:

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

    ...

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

        ...

    })

    ....

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: 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 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. Modify "view" permission to make form read only: Ok but i have an other solution see above

这篇关于在 Django 中查看权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆