如何修改django以创建"查看"权限?

Gre*_*tle 31 django django-admin django-permissions

我最近开始使用django管理一个使用twisted.web多年来有机增长的大型现有应用程序.我开始尝试使用django,它是自动管理界面,我对结果非常满意.

对我来说似乎缺少的一件事是能够为用户提供对数据的只读访问权限.例如,我们有一个角色,允许人们登录并创建采购订单.他们还需要能够查看,但不能编辑其他客户端或产品数据.

如何在django admin中创建"查看"权限,以便用户可以修改某些表的数据,同时只读取其他表的访问权限?

更新:Django Admin似乎给了我CRUD界面的CUD.如何获取具有关联权限和组的只读部分?

更新2010年2月12日:Django 1.2现在将包含只读.详情如下.


我猜我回答了自己的问题.将内容下移到下面的真实答案.

Gre*_*tle 35

这就是我改变Django 1.0.2以添加"查看"权限的方法.对不起,没有差异可用.

[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)
Run Code Online (Sandbox Code Playgroud)

[X] 2.测试'视图'权限被添加到所有模型

run manage.py syncdb
Run Code Online (Sandbox Code Playgroud)

我确认现在为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()
Run Code Online (Sandbox Code Playgroud)

[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
Run Code Online (Sandbox Code Playgroud)

[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 %}
Run Code Online (Sandbox Code Playgroud)

[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'])
Run Code Online (Sandbox Code Playgroud)

[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']),
Run Code Online (Sandbox Code Playgroud)

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

如果用户具有"查看"权限和"更改"权限,则不执行任何操作.更改覆盖视图.

如果用户具有"查看"权限而没有"更改",则更改默认表单并将DISABLED或READONLY属性添加到表单元素.并非所有浏览器都支持此功能,但出于我的目的,我可以要求用户使用正确的浏览器. 禁用/只读示例

发现并非所有浏览器都尊重"readonly",因此它将一些控件设置为readonly,其他控件设置为disabled.这允许用户在需要时从文本控件复制数据.

#/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 %}
Run Code Online (Sandbox Code Playgroud)

  • @GreatTurtle感谢您的回答!嗯,我正在使用djano 1.6,但它没有查看权限.我按照你的回答但没有任何作用.任何选择! (2认同)

小智 11

此代码段将使超级用户成为唯一具有写访问权限的用户.

class AdminOwn(admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return self.readonly_fields
        #get all fields as readonly
        fields = [f.name for f in self.model._meta.fields]
        return fields
Run Code Online (Sandbox Code Playgroud)


Vin*_*jip 6

它就在管理员那里.您可以在管理员中为用户和组设置权限,以添加,更改和删除特定模型.

更新:对不起,我误解了这个问题,因为我误解了单词视图,给它Django含义而不是"只读".如果你想使用管理员只读,我认为你需要做一些工作.看到这个帖子,James Bennett(Django发布经理)说:

正如您通过搜索此列表的档案所找到的,这不是Django管理界面旨在支持的内容,因此任何解决方案都需要完全来自您编写自己的代码.

Django管理员使用三种权限:"添加","更改"和"删除".没有"查看但不做任何修改"的许可,因此如果不进行重要的自定义编码,就无法应用此类限制.

额外的工作将涉及您为某些模型添加"只读"权限,并更改基本管理模板以检查用户是否具有该权限 - 如果是,则禁用某些控件(如保存按钮)并使其他人只读.这将防止随意摆弄,但你也可能需要修改服务器端逻辑来检查相同的权限,以避免偷偷摸摸绕过权限作出任何职位.


Gre*_*tle 2

Django 版本 1.2 中现已包含向管理视图添加只读字段的功能。

请参阅票号 342 http://code.djangoproject.com/ticket/342

请参阅变更集编号 11965 http://code.djangoproject.com/changeset/11965

请参阅文档 http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields

  • readonly_fields != 只读权限。每个用户都不容易配置。 (24认同)