最近有点忙开源django信息管理系统,更新这个公众号的时间又要挤了。但是权限很重要,有点抽象,所以只能慢慢写,希望能用通俗易懂的语言和例子,帮助大家理解如何控制和管理用户权限。实战教程中:开发企业级应用智能文档管理系统(1),我们开发了一个叫app的app,已经搭建了基础框架,实现了如下功能页面(黄色部分)。实现了)。
本文是教程的第二部分,重点介绍用户权限控制和管理。关于文档搜索和 Ajax 搜索功能我们将放在教程的最后部分。
权限管理需求分析
权限机制可以约束用户行为,控制页面的显示内容,让我们的应用更加灵活强大。一个完整的用户权限应该包含3个要素:用户、对象和权限,即什么用户对什么对象有什么样的权限。
以文档系统为例,我们的对象有 3 个类:产品、类别和文档。我们的权限主要包括view(查看)、(添加)、()和()。我们的用户大致可以分为以下几类。根据用户分类,我们需要设置不同的权限。
另外,为了增加难度,我们还需要在权限管理中增加一项。每个用户只能更改自己创建的对象(产品、类别和文档)的信息。下面我们来看看如何实现客户的权限管理需求。
看不到不代表做不到
有很多这样的网站。登录前,用户看到一个页面,登录后,他们看到另一个页面。通常,登录后的页面包含更多的内容和信息。初学者可能会说,这不就是权限管理吗?答案是不。我们会用实际案例告诉你。看不到不代表做不到。
我们先来看一个产品列表的案例。在模板中,我们使用 .user。确定用户是否已登录。如果用户已登录,列表下方将显示添加产品的链接。
{% if request.user.is_authenticated %}
添加产品
{% else %}
请先[url={% url 'account_login' %}?next=
{% url 'smartdoc:product_create' %}]登录[/url]添加产。
{% endif %}
匿名用户看到这样的页面。
用户登录后,他们可以看到 + 添加产品按钮。
那么问题来了,匿名用户看不到+添加产品按钮,但是如果用户直接访问产品创建页面////呢?我们直接上图(见下图)。惊讶与否,惊讶与否?不是只能由登录用户创建产品吗?原因是我们在前端只根据用户是否登录显示不同的内容,并没有在后端视图中判断和执行用户是否登录或者他有什么权限。对于权限控制,后端显然比前端更重要,因为判断用户是否有权限,可以进行哪些操作,显然是逻辑问题,而不是前端显示问题。
要真正实现用户登录后可以创建产品,我们必须在后台修改视图,使其真正执行我们设置的权限。最简单的方法是使用 @ 装饰器。因为我们使用的是基于类的视图(Class Based View)而不是函数视图开源django信息管理系统,所以我们还需要使用@装饰器,首先将类伪装成函数,然后再使用@装饰器。
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
@method_decorator(login_required, name='dispatch')
class ProductCreate(CreateView):
model = Product
template_name = 'smartdoc/form.html'
form_class = ProductForm
# Associate form.instance.user with self.request.user
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
@This装饰器的作用是当用户尝试访问某个页面时,会要求用户先登录,用户登录后会自动重定向到该页面。此时,如果匿名用户访问创建页面//// 再次直接跳转到登录页面,只有登录后才会跳转到产品创建页面(如下图)。
恭喜,你已经可以实现最简单的权限管理了。请记住,真正的权限管理在后台。
约翰和克里斯的区别
是否登录只能区分匿名用户和注册用户,但在实际应用中,不同的注册用户也有不同的权限。对于此示例,假设我们有两个注册用户 John 和 Chris天外神坛源码网,具有以下权限。我们如何控制实施?
最好的方法是使用内置的权限管理。内置模型与User是多对多的关系,并有对应的数据表。每个模型创建完成后,模型的添加,三个(2.1和视图)会默认添加到数据表中。例如,定义一个名为 的模型,会自动创建相应的三个: 和 。稍后我们会系统地介绍权限管理和群组。
以系统为例,系统为每个对象(文档、类别和产品)生成了三种权限。但是此时数据表中的权限还没有和用户建立关系,只是一些字段而已。我们需要登录admin后找到Chris和John,并添加相应的权限。Chris 比 John 多了两个权限:添加文档和文档。注意:添加后不要忘记点击保存。
如果此时让约翰登录,你会发现他仍然可以上传文件(如下图)。系统不工作吗?当然不是。使用内置权限管理系统的关键分为两步:第一步是为用户设置相应的权限,第二步是判断用户在模板和视图中是否有相应的权限。我们只完成了第一步,它是如何工作的?
判断用户在模板中是否有权限
可以在模板中使用全局变量 perms 来确定当前用户的所有权限。在下面的例子中,我们在.html模板中使用perms来检测当前用户是否有权限添加文档()和添加产品(),如果有则显示相应的按钮。
{% if request.user.is_authenticated %}
{% if perms.smartdoc.add_document %}
上传文档 |
{% endif %}
{% if perms.smartdoc.add_product %}
添加产品
{% endif %}
{% else %}
请先登录添加产品,编辑产品或上传文档。
{% endif %}
由于 John 只有添加产品的权限,没有上传文件的权限,所以我们应该看到添加产品的按钮,而不是上传文件的按钮。我们来看看最终的结果,不就是这样吗?
如果 Chris 访问同一页面,他必须在前端再看到一个按钮。恭喜,我们实现了注册用户的差异化。事情就这样结束了吗?明显不是。让我们重温那一段。对于权限控制,后端显然比前端更重要,因为判断用户是否有权限,可以进行哪些操作,显然是逻辑问题,而不是前端显示问题。
判断用户在视图中是否有权限
在视图中,可以使用 user.() 方法判断一个用户是否有相应的权限。当然,最快的方法是使用@装饰器,它可以将权限验证和核心业务逻辑分开,使代码更加简洁和合乎逻辑。更清晰。在下面的示例中,只有登录并具有“添加产品”权限的用户才能创建产品。
from django.contrib.auth.decorators import login_required, permission_required
from django.utils.decorators import method_decorator
@method_decorator(login_required, name='dispatch')
@method_decorator(permission_required('smartdoc.add_product', raise_exception=True), name='dispatch')
class ProductCreate(CreateView):
model = Product
template_name = 'smartdoc/form.html'
form_class = ProductForm
# Associate form.instance.user with self.request.user
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
未经许可强行访问页面只会导致403错误,如下图所示。
系统缺陷
内置系统仅对模型有用,对特定模型无效。一旦用户有权编辑文档,该用户将有权编辑所有文档。在这种情况下,我们不是说会更难吗?每个用户只能编辑他们创建的对象(产品、类别或文档)。这时候我们可以通过方法来实现,参与如何使用通用视图等方法。如果用户尝试访问不是自己创建的内容,则会出现 404 错误。
from django.contrib.auth.decorators import login_required, permission_required
from django.utils.decorators import method_decorator
@method_decorator(login_required, name='dispatch')
@method_decorator(permission_required('smartdoc.change_product', raise_exception=True), name='dispatch')
class ProductUpdate(UpdateView):
model = Product
template_name = 'smartdoc/form.html'
form_class = ProductForm
def get_object(self, queryset=None):
obj = super().get_object(queryset=queryset)
if obj.author != self.request.user:
raise Http404()
return obj
概括
本文以智能文档系统为例,详细介绍如何在前后端对用户权限进行检查和管理,从而实现我们项目对用户权限管理的需求。在本教程中,我们通过admin后台为每个用户添加一个用户的权限,这在用户众多的情况下显然是不现实的。两种比较好的方式是(1)创建用户时直接分配权限(2)创建权限组group。另外403和404页面也很简单。小编会在后面介绍上篇文章)和群,并介绍403和404页面的定制,欢迎关注我的微信公众号。
大河狗
2018.8.22
|