Python 在 Django 中查看权限
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23104449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
View permissions in Django
提问by Tameen Malik
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!
由于 django admin 在它的 auth 中有三个权限:添加、更改、删除!我想在管理面板的此身份验证中添加查看权限。我知道我必须自定义权限才能在“身份验证|权限|可以查看权限”中添加查看权限才能查看所有条目!
THE WAY:
道路:
[X] 1. Added 'view' to default permission list
[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. Test the 'view' permission is added to all models
[X] 2. 测试所有模型添加'view'权限
run manage.py syncdb
I confirmed that view permission is now added for all tables in the auth_permissions table
我确认现在为 auth_permissions 表中的所有表添加了查看权限
[X] 3. Add "get_view_permission" to default model class.
[X] 3.在默认模型类中添加“get_view_permission”。
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.
向模型类添加了 get_view_permission。您可以在文件 ./db/models/options.py 中找到它。下一步中的 admin 类将使用它。
def get_view_permission(self):
return 'view_%s' % self.object_name.lower()
[X] 4. Add "has_view_permission" to default admin class
[X] 4. 添加“has_view_permission”到默认管理类
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.
为了保持一致,我将向系统添加“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. Update default template to list models if user has view permission
[X] 5. 如果用户有查看权限,更新默认模板以列出模型
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.
我修改了 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. Confirm user can "view" but not "change" the model
[X] 6.确认用户可以“查看”但不能“更改”模型
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.
发现 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. Remove "Save and Add another" button if user is viewing an item
[X] 7. 如果用户正在查看一个项目,删除“保存并添加另一个”按钮
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.
再次修改 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. Modify "view" permission to make form read only
[X] 8.修改“查看”权限,使表单只读
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]
如果用户具有“查看”权限而没有“更改”,则更改默认表单并将 DISABLED 或 READONLY 属性添加到表单元素。并非所有浏览器都支持这一点,但出于我的目的,我可以要求用户使用正确的浏览器。[禁用/只读示例][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?
答案来源:?如何修改 django 以创建“查看”权限?
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!**
问题:按照上面的回答我已经完成并且可以看到这个 127.0.0.1:8000/en-us/admin/ 页面为只读 **但用户中的用户不可见 127.0.0.1:8000/en-us/管理员/用户。需要帮忙!**
采纳答案by MoiTux
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 2.1 为默认权限添加了查看权限。下面的解决方案可能适用于早期版本的 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
这是在 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] 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.
is useless any more:
[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
And that the case for all of those methods get_foo_permission
所有这些方法的情况 get_foo_permission
[X] 4. Add "has_view_permission" to default admin class
should be:
[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
...
Do the modification on get_model_perms
to include 'view', in the same idea do this one:
进行修改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
...
})
....
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
允许“右视图”呈现页面(一个对象的)并禁用“右视图”以保存在页面上所做的修改,避免 [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
[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
and [X] 7. Remove "Save and Add another" button if user is viewing an item
: should be ok but i did that:
[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. Modify "view" permission to make form read only: Ok but i have an other solution see above
[X] 8.修改“查看”权限使表单只读:好的,但我有其他解决方案见上文
回答by pcoronel
Adding 'view' permission to default permissionslist
将“查看”权限添加到默认权限列表
Your solution works, but you should really avoid editing source code if possible. There's a few ways to accomplish this within the framework:
您的解决方案有效,但您应该尽可能避免编辑源代码。有几种方法可以在框架内实现这一点:
1. Add the permissionduringpost_syncdb()
:
In a file under your_app/management/
在 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)
Whenever you issue a 'syncdb' command, all content types can be checked to see if they have a 'view' permission, and if not, create one.
每当您发出“syncdb”命令时,都可以检查所有内容类型以查看它们是否具有“查看”权限,如果没有,则创建一个。
- SOURCE: The Nyaruka Blog
- 来源:Nyaruka 博客
2. Add the permission to the Meta permissions option:
Under every model you would add something like this to its Meta
options:
在每个模型下,您都可以在其Meta
选项中添加如下内容:
class Pizza(models.Model):
cheesiness = models.IntegerField()
class Meta:
permissions = (
('view_pizza', 'Can view pizza'),
)
This will accomplish the same as 1except you have to manually add it to each class.
这将完成与1相同的操作,但您必须手动将其添加到每个类中。
3. NEW in Django 1.7, Add the permission to the Meta default_permissions option:
3.在 Django 1.7中新增,在Meta default_permissions 选项中添加权限:
In Django 1.7 they added the default_permissions Meta option. Under every model you would add 'view' to the default_permissions option:
在 Django 1.7 中,他们添加了 default_permissions Meta 选项。在每个模型下,您都可以在 default_permissions 选项中添加“view”:
class Pizza(models.Model):
cheesiness = models.IntegerField()
class Meta:
default_permissions = ('add', 'change', 'delete', 'view')