【问题标题】:View permissions in Django [duplicate]在 Django 中查看权限 [重复]
【发布时间】:2014-05-31 00:44:58
【问题描述】:

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

方法:

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

#./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. 测试所有模型都添加了'view'权限

run manage.py syncdb

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

[X] 3. 将“get_view_permission”添加到默认模型类。

向模型类添加了 get_view_permission。您可以在文件 ./db/models/options.py 中找到它,这将在下一步中由管理类使用。

def get_view_permission(self):

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

[X] 4. 将“has_view_permission”添加到默认管理类

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

# /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. 如果用户有查看权限,则更新默认模板以列出模型

我修改了 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>

    {% 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. 确认用户可以“查看”但不能“更改”模型

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

'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': 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.修改“查看”权限使表单只读

如果用户拥有“查看”权限和“更改”权限,则什么也不做。更改覆盖视图。

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

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

#/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 %}

答案来源:​How can I MODIFY django to create "view" permission?

问题:在完成上述回答后,我已经完成并且可以将此 127.0.0.1:8000/en-us/admin/ 页面视为只读 **但用户中的用户不可见 127.0.0.1: 8000/en-us/admin/user 。需要帮助!**

【问题讨论】:

标签: python permissions django-1.6


【解决方案1】:

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


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

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

[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))

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

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 上进行修改以包含“视图”,以同样的想法执行此操作:

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

@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)

    ...

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

@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

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: 应该没问题,但我做到了:

'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. 修改“查看”权限以使表单只读:好的,但我有其他解决方案见上文

【讨论】:

  • 谢谢 :) 但我不明白第 3 步 - 并且是文件 contrib/admin/options.py@MoiTux 的第 4 步
  • 这会生成错误:/admin/auth/user/ 处的 AttributeError 异常类型:AttributeError 异常值:'UserAdmin' 对象没有属性 'has_view_permission' 异常位置:\django\contrib\admin\options。 py 在 changelist_view 中,第 1295 行
  • @TameenMalik contrib/admin/options.py 的想法是在“每次”有 has_change_permission 时添加 has_view_permission。我没有收到任何错误,但我只是使用基本管理员进行测试。
  • @TameenMalik 我可以毫无问题地访问用户的管理员
  • @TameenMalik 很抱歉,我在复制/粘贴代码时出错了。现在应该可以了。
【解决方案2】:

default permissions 列表添加“查看”权限

您的解决方案有效,但您应该尽可能避免编辑源代码。在框架内有几种方法可以实现这一点:

1. Add the permission期间 post_syncdb()

在 your_app/management/ 下的文件中

from django.db.models.signals import post_syncdb
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission

def add_view_permissions(sender, **kwargs):
    """
    This syncdb hooks takes care of adding a view permission too all our 
    content types.
    """
    # for each of our content types
    for content_type in ContentType.objects.all():
        # build our permission slug
        codename = "view_%s" % content_type.model

        # if it doesn't exist..
        if not Permission.objects.filter(content_type=content_type, codename=codename):
            # add it
            Permission.objects.create(content_type=content_type,
                                      codename=codename,
                                      name="Can view %s" % content_type.name)
            print "Added view permission for %s" % content_type.name

# check for all our view permissions after a syncdb
post_syncdb.connect(add_view_permissions)

每当您发出“syncdb”命令时,所有内容类型都可以 检查他们是否有“查看”权限,如果没有,创建 一个。

2。给Meta permissions option添加权限:

在每个模型下,您都可以在其Meta 选项中添加类似的内容:

class Pizza(models.Model):
    cheesiness = models.IntegerField()

    class Meta:
        permissions = (
            ('view_pizza', 'Can view pizza'),
        )

这将与 1 完成相同的操作,但您必须手动将其添加到每个类中。

3. Django 1.7 中的新功能,将权限添加到Meta default_permissions option

在 Django 1.7 中,他们添加了 default_permissions 元选项。在每个模型下,您都可以将“视图”添加到 default_permissions 选项:

class Pizza(models.Model):
    cheesiness = models.IntegerField()

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

【讨论】:

  • 我将这个答案发布到用户的相同(但更清晰)问题Add Permission to Django Admin
  • 如果你还没有使用 1.7,我建议你现在只做 #1 或 #2 ——它们完成与 #3 相同的事情,但适用于早期版本的 Django。虽然如果升级到 1.7 对您的系统/程序来说不会太困难,那就去吧。归根结底,重点是不要修改源代码,而是使用上述方法之一,然后只需使用user.has_perm('my_app.view_mymodel') 测试用户是否有权限。
猜你喜欢
  • 1970-01-01
  • 2020-04-29
  • 2011-02-20
  • 2020-01-21
  • 1970-01-01
  • 2013-05-15
  • 2016-01-17
  • 2015-02-12
相关资源
最近更新 更多