我最近开始使用django来管理使用twisted.web多年来有机增长的大型现有应用程序。我开始尝试使用django,它是自动管理界面,我对结果非常满意。
我的目的似乎缺少的一件事是能够为用户提供对数据的只读访问权限。例如,我们有一个角色,允许人们登录并创建采购订单。他们还需要能够查看,但不能编辑其他客户端或产品数据。
如何在django admin中创建“查看”权限,以便用户可以修改某些表的数据,同时只读取其他表的访问权限?
更新:Django Admin似乎给了我CRUD界面的CUD。如何获取具有关联权限和组的只读部分?
2010年2月12日更新:Django 1.2现在将包含只读。详情如下。
答案 0 :(得分:35)
这就是我改变Django 1.0.2以添加“查看”权限的方式。对不起,没有差异可用。
#./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 manage.py syncdb
我确认现在为auth_permissions表中的所有表添加了视图权限
将get_view_permission添加到模型类。您可以在./db/models/options.py文件中找到它。管理类将在下一步中使用它。
def get_view_permission(self):
return 'view_%s' % self.object_name.lower()
为了保持一致,我要将“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
我修改了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 %}
发现contrib / admin / templatetags / admin_modify.py似乎控制了保存/保存和继续按钮的显示与否。将“保存”字段更改为默认值始终为True,以检查上下文和权限。如果用户有更改或添加权限,他们应该可以保存。
'show_save': (change and context['has_change_permission']) or (context['add'] and context['has_add_permission'])
再次修改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']),
如果用户具有“查看”权限和“更改”权限,则不执行任何操作。更改覆盖视图。
如果用户具有“查看”权限而没有“更改”,则更改默认表单并将DISABLED或READONLY属性添加到表单元素。并非所有浏览器都支持此功能,但出于我的目的,我可以要求用户使用正确的浏览器。 Disabled / Readonly example
发现并非所有浏览器都尊重“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 %}
答案 1 :(得分: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
答案 2 :(得分:6)
就在管理员那里。您可以在管理员中为用户和组设置权限,以添加,更改和删除特定模型。
更新:抱歉,我误解了这个问题,因为我误解了单词视图,给它Django含义而不是“只读”。如果你想使用管理员只读,我认为你需要做一些工作。见this thread,James Bennett(Django发布经理)说:
通过搜索你会发现 这个列表的档案,这不是 Django管理界面的东西 旨在支持,所以任何 解决方案需要完全解决 从你编写自己的代码。
和
Django管理员运行三个 权限:“添加”,“更改”和 “删除”。没有“观点而是制造 没有修改“许可,因此 没有办法申请这样的 限制没有重要 自定义编码。
额外的工作将涉及为某些模型添加“只读”权限,并更改基本管理模板以检查用户是否具有该权限 - 如果是,则禁用某些控件(如保存按钮)并制作其他模板只读。这样可以防止随意修改,但您可能还需要修改服务器端逻辑以检查相同的权限,以避免以偷偷摸摸的方式进行任何POST以绕过权限。
答案 3 :(得分:3)
您可以在模型中创建“只读”权限,并使用jasuca的代码进行修改:
models.py:
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=256, null=True, blank=True)
class Meta:
permissions = (
('readonly_mymodel','Readonly MyModel'),
)
admin.py:
class MyModelAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if not request.user.is_superuser and request.user.has_perm('mymodel.readonly_mymodel'):
return [f.name for f in self.model._meta.fields]
return self.readonly_fields
在应用程序的管理员中,您必须向用户授予“更改”和“只读”权限。
答案 4 :(得分:2)
现在,Django 1.2版中包含了向管理视图添加只读字段的功能。
见票号342 http://code.djangoproject.com/ticket/342
请参阅变更集编号11965 http://code.djangoproject.com/changeset/11965
答案 5 :(得分:0)
您可以在auth模块中创建组。然后在admin.py中根据用户组登录,设置modeladmin的readonly_fields属性。添加方法def has_add_permission(self,request)为具有readonly权限的组返回false。为组添加,修改权限。他们只能读取模型属性。