如何避免 django 的权限字符串中的拼写错误
How to avoid typos in django's permission strings
根据文档,可以像这样创建和使用自定义权限:
class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
)
使用权限:
user.has_perm('app.view_task')
来源:https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#custom-permissions
如果权限字符串中有错字。例如:我使用user.has_perm('app.view_tasks')
,那么这个错别字就不会被注意到了。
目标 1
如果不使用现有权限,我希望收到异常或警告。
目标 2
首先为了避免拼写错误,我想要常量:user.PERM_APP_VIEW_TASKS
或类似的东西。
目标 1
创建自定义装饰器:
警告!未经测试的代码!!!!!
@permission_required
def assert_permission(permission):
def real_decorator(original_function):
def wrapper(request, *args, **kwargs):
permission_object = Permission.objects.filter(codename=permission)
if not permission_object.exists():
raise ValueError("This permission does not exist!")
original_function(request, *args, **kwargs)
return wrapper
return real_decorator
目标 2
向您的模型添加常量 类 并在请求特定权限时引用这些常量。
示例:
class Task(models.Model):
MY_PERMISSION_CONSTANT = 'app.view_task'
...
class Meta:
permissions = (
(MY_PERMISSION_CONSTANT, "Can see available tasks"),
)
@permission_required(Task.MY_PERMISSION_CONSTANT)
def some_view(request):
pass
目标 1
覆盖 ModelBackend
class 的 has_perm
方法,来自我的 backends.py
文件:
import logging
from difflib import get_close_matches
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
class ModelBackendHelper(ModelBackend):
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_active:
return False
else:
obj_perms = self.get_all_permissions(user_obj, obj)
allowed = perm in obj_perms
if not allowed:
if settings.DEBUG:
similar = get_close_matches(perm, obj_perms)
if similar:
logging.warn("{0} not found, but is similar to: {1}".format(perm, ','.join(similar)))
return allowed
工作原理:
与has_perm
相同的逻辑,但如果settings.DEBUG
是True
,并且发现perm
的相似版本,则输出级别WARN
的警告日志消息:
WARNING:root:myapp.view_tasks not found, but is similar to: myapp.view_task
在settings.py
中更改AUTHENTICATION_BACKENDS
的值:
AUTHENTICATION_BACKENDS = ['myapp.backends.ModelBackendHelper']
这既可以用于生产环境,也可以用于开发环境,但我个人不会将其包含在生产站点中,我希望当一切都进入生产环境时,权限会得到整合。
目标 2
权限属于模型,为了保持干燥,我重新使用了 Meta
:
中定义的权限
from django.db import models
class Task(models.Model):
name = models.CharField(max_length=30)
description = models.TextField()
class Meta:
permissions = (
("view_task", "Can see available tasks"),
)
def _get_perm(model, perm):
for p in model._meta.permissions:
if p[0] == perm:
return p[0]
err = "Permission '{0}' not found in model {1}".format(perm, model)
raise Exception(err)
def format_perm(perm):
return '{0}.{1}'.format(__package__, perm)
def get_perm(model, type):
return format_perm(_get_perm(model, type))
PERM_APP_VIEW_TASK = get_perm(Task, "view_task")
可以使用 get_perm
或快捷方式 PERM_APP_VIEW_TASK
:
访问权限
models.PERM_APP_VIEW_TASK
# or
get_perm(Task, "view_task")
# or
format_perm(_get_perm(Task, "view_task"))
如果搜索丢失的权限 get_perm
将引发 Exception
:
PERM_APP_VIEW_TASK = get_perm(Task, "add_task")
留言:
Exception: Permission 'add_task' not found in model <class 'myapp.models.Task'>
根据文档,可以像这样创建和使用自定义权限:
class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
)
使用权限:
user.has_perm('app.view_task')
来源:https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#custom-permissions
如果权限字符串中有错字。例如:我使用user.has_perm('app.view_tasks')
,那么这个错别字就不会被注意到了。
目标 1
如果不使用现有权限,我希望收到异常或警告。
目标 2
首先为了避免拼写错误,我想要常量:user.PERM_APP_VIEW_TASKS
或类似的东西。
目标 1
创建自定义装饰器:
警告!未经测试的代码!!!!!
@permission_required
def assert_permission(permission):
def real_decorator(original_function):
def wrapper(request, *args, **kwargs):
permission_object = Permission.objects.filter(codename=permission)
if not permission_object.exists():
raise ValueError("This permission does not exist!")
original_function(request, *args, **kwargs)
return wrapper
return real_decorator
目标 2
向您的模型添加常量 类 并在请求特定权限时引用这些常量。 示例:
class Task(models.Model):
MY_PERMISSION_CONSTANT = 'app.view_task'
...
class Meta:
permissions = (
(MY_PERMISSION_CONSTANT, "Can see available tasks"),
)
@permission_required(Task.MY_PERMISSION_CONSTANT)
def some_view(request):
pass
目标 1
覆盖 ModelBackend
class 的 has_perm
方法,来自我的 backends.py
文件:
import logging
from difflib import get_close_matches
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
class ModelBackendHelper(ModelBackend):
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_active:
return False
else:
obj_perms = self.get_all_permissions(user_obj, obj)
allowed = perm in obj_perms
if not allowed:
if settings.DEBUG:
similar = get_close_matches(perm, obj_perms)
if similar:
logging.warn("{0} not found, but is similar to: {1}".format(perm, ','.join(similar)))
return allowed
工作原理:
与has_perm
相同的逻辑,但如果settings.DEBUG
是True
,并且发现perm
的相似版本,则输出级别WARN
的警告日志消息:
WARNING:root:myapp.view_tasks not found, but is similar to: myapp.view_task
在settings.py
中更改AUTHENTICATION_BACKENDS
的值:
AUTHENTICATION_BACKENDS = ['myapp.backends.ModelBackendHelper']
这既可以用于生产环境,也可以用于开发环境,但我个人不会将其包含在生产站点中,我希望当一切都进入生产环境时,权限会得到整合。
目标 2
权限属于模型,为了保持干燥,我重新使用了 Meta
:
from django.db import models
class Task(models.Model):
name = models.CharField(max_length=30)
description = models.TextField()
class Meta:
permissions = (
("view_task", "Can see available tasks"),
)
def _get_perm(model, perm):
for p in model._meta.permissions:
if p[0] == perm:
return p[0]
err = "Permission '{0}' not found in model {1}".format(perm, model)
raise Exception(err)
def format_perm(perm):
return '{0}.{1}'.format(__package__, perm)
def get_perm(model, type):
return format_perm(_get_perm(model, type))
PERM_APP_VIEW_TASK = get_perm(Task, "view_task")
可以使用 get_perm
或快捷方式 PERM_APP_VIEW_TASK
:
models.PERM_APP_VIEW_TASK
# or
get_perm(Task, "view_task")
# or
format_perm(_get_perm(Task, "view_task"))
如果搜索丢失的权限 get_perm
将引发 Exception
:
PERM_APP_VIEW_TASK = get_perm(Task, "add_task")
留言:
Exception: Permission 'add_task' not found in model <class 'myapp.models.Task'>