所有的应用程序都需要某种检查或权限,以控制每个用户可以做什么,并确定用户是否经过认证。 在这篇文章中,你将学习如何设置多个用户角色,以及如何根据用户角色来设置用户权限。此外,我将说明如何使用Django内置的Users and Groups来为多个用户应用权限。 虽然很多文章只涉及用户权限和默认的Django用户权限,但我将更进一步,建立一个具有不同用户角色的应用程序,然后根据用户的角色来设置权限。
前提条件
要学习这篇文章,需要具备以下条件:
- 对Django和Python有初步的工作经验
- 安装了Python 3.7或更高版本
使用Django的内置权限
默认情况下,Django提供了一个内置的授权(permissions)。这个功能使你能够定义每个用户被允许执行的动作。该框架包括Users 和Groups 的内置模型,用于为一组用户提供权限,指定用户是否可以执行任务的权限/标志,限制内容的视图工具等。当django.contrib.auth 列在你的INSTALLED_APPS ,它将提供四个默认的权限--添加、更改、删除和每个模型的视图。 现在,让我们假设你有一个项目,有一个应用程序product 和一个模型Order 。为了测试哪些用户有基本权限,你可以使用以下代码:
python manage.py shell
user = User.objects.first()
- 添加:
user.has_perm('product.add_order') - 改变:
user.has_perm('product.change_order') - delete: 删除。
user.has_perm('product.delete_order') - view:
user.has_perm('product.view_order')通过使用Django内置的装饰器permission_required,可以添加权限,将一个函数限制在只有拥有该特定权限的用户身上。
from django.contrib.auth.decorators import permission_required
@permission_required('product.change_name')
def admin_view(request):
"""Raise permission denied exception or redirect user"""
如果你使用的是基于类的视图,你只需要使用一个混合素,PermissionRequiredMixin :
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic import ListView
class ProductListView(PermissionRequiredMixin, ListView):
permission_required = 'product.change_name'
如何向模型添加自定义权限
如果权限没有在视图中说明,你可以在你的模型中指定它们。附加权限是在模型的class Meta ,使用权限字段来完成。你将能够根据你的需要指定尽可能多的权限,但它必须是一个元组。例如,你可以定义一个权限,允许用户像这样改变产品的名称。
from django.db import models
class Product(models.Model):
user = models.ForeignKey(User)
class Meta:
permissions = (("change_name", "can change name of product"),)
为了实现这些变化,运行python manage.py makemigrations 和migrate 。
如何向模板添加自定义权限
用户的权限可以通过在模板中调用{{ perms }} 来检索。要检查一个特定的用户是否有查看模板的权限,你所要做的就是从持有权限的特定模型中获取perms 。它应该看起来像这样。
{{ perms.<name_of_app>.<permission>}} 例如,{{ perms.app.change_name }} 。通过 if语句,你可以为你的模板的特定部分添加一个权限。
{% if perms.app.change_name %}
<p>can change name of product</p>
{% endif %}
通过这样做,只有拥有change_name 权限的用户才能使用模板的那个特定部分。
如何为视图添加自定义权限
就像你在使用内置的Django权限时一样,你也可以通过使用permission_required 装饰器向视图添加自定义权限,或者在基于类的视图中,使用PermissionRequiredMixin 。 对于基于函数的视图:
from django.contrib.auth.decorators import permission_required
@permission_required('app.change_name')
def the_view(request):
...
对于基于类的视图:
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
permission_required = 'app.change_name'
# Or multiple permissions
permission_required = ('app.change_name', 'app.edit_name')
# Note that 'catalog.can_edit' is just an example, you can replace it with
# whatever permissions you have created
注意
如果一个用户不被允许访问一个view ,并且他们试图访问它,PermissionRequiredMixin 和@permission_required 的行为是不同的。@permission_required 重定向到登录屏幕,PermissionRequiredMixin 返回HTTP 403 (Status Forbidden) 如果一个用户已经登录但没有正确的权限。
在构建应用程序时,PermissionRequiredMixin 的默认行为是最佳的。要在基于函数的视图中复制这种行为,你必须添加@login_required 装饰器,并将@permission_required 与raise_exception=True 。这就是它的外观:
from django.contrib.auth.decorators import login_required, permission_required
@login_required
@permission_required('app.change_name', raise_exception=True)
def the_view(request):
...
为多个用户类型添加权限
通常,当你要实现多个用户类型时,你需要确保每个用户类型都有一些限制。例如,如果你正在建立一个作业应用程序,教师可以设置问题,学生只能回答问题。在这种情况下,你必须设置权限系统,使学生不能选择设置问题。为了说明这一点,让我们假设你试图建立一个应用程序,其中经过认证的教师可以创建作业,经过认证的学生可以回答问题。 假设我们的models.py 文件是这样的:
from django.contrib.auth.models import AbstractUser
from django.db import models
**class** **User**(AbstractUser):
is_student **=** models**.**BooleanField(default**=**False)
is_teacher **=** models**.**BooleanField(default**=**False)
**class** **Student**(models**.**Model):
user **=** models**.**OneToOneField(User, on_delete**=**models**.**CASCADE, primary_key**=**True)
subjects **=** models**.**ManyToManyField(Subject, related_name**=**'subject')
为了处理这些不同用户的权限,你需要创建一个你自己的自定义装饰器:
# decorator.py
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
def for_students(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='login'):
'''
A decorator to check logged in user could be a student and redirects to the login page if the user isn't authenticated.
'''
actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_student,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
def for_teachers(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='login'):
'''
A decorator to check whether the logged-in user is a teacher and
redirect to the login page if the user is not authenticated.
'''
actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_teacher,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator-
现在,要在视图中使用它们,你所需要做的就是像以前那样调用它。它应该看起来像这样:
# views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
from .decorators import for_students, for_teachers
from .models import Assignment #this is an assumption
@login_required
@student_required # <-- here is the decorator
def answer_assignment(request, pk):
quiz = get_object_or_404(Assignment, pk=pk)
student = request.user.student
# body of the view...
如果你使用的是基于类的视图,你的视图将看起来像这样:
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from .decorators import for_students
@method_decorator([login_required, student_required], name='dispatch')
class AnswerAssignment(CreateView):
# body of the view...
向一个组添加权限
值得庆幸的是,Django让你很容易通过默认提供的管理面板来创建组。 本节将包含一个关于你如何在你的应用程序中为组添加权限的说明。让我们假设你正在建立一个提供房地产建议的网站,如果一个用户订阅了 "Tier 1",他们可以查看3个建议,而 "Tier 2 "可以查看6个建议。 考虑到上述情况,你的models.py 文件将看起来像这样:
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
first_name = models.CharField(blank = True, max_length = 20)
last_name = models.CharField(blank = True, max_length = 20)
# You can add more User fields as required
# define the custom permissions
# related to User.
class Meta:
permissions = (("tier_1", "Can view 3 suggestions"), ("tier_2", "Can view 6 suggestions"),
# You can add other custom permissions as required
)
如果你在Django中使用AbstractUser ,你必须添加AUTH_USER_MODEL = 'YourAppName.YourClassName' 。这样,你就告诉Django使用我们的自定义用户模型,而不是默认的。下面的代码应该放在你的admin.py 文件中,这样你就可以看到你的用户模型。
from django.contrib import admin
from .models import User
admin.site.register(User)
为了实现这些变化,运行$ python manage.py makemigrations 和$ python manage.py migrate 。 接下来,你将创建一个超级用户,用来创建组。要做到这一点,运行$ python3 manage.py createsuperuser ,并填写必要的细节。 现在,用$ python manage.py runserver ,运行你的服务器,并前往管理员,用你刚刚创建的用户细节登录。这是登录后你应该看到的:
接下来你要做的是点击 "Group"行的 "+ Add"按钮。 你会被提示一个看起来像这样的表格:

你会看到,你可以选择各种权限,并将它们附加到一个特定的组。
总结
这篇文章的目的是让你从不知道如何在Django应用程序中管理权限到向你展示在构建Django应用程序时可以操作和管理权限的不同方式。希望我能够做到这一点。通过这篇文章,你应该已经学会了如何向视图、模型和模板添加权限。我还展示了你如何能够潜在地创建你自己的自定义权限。最后,我还展示了如何使用Django管理面板向组添加权限。现在你已经学会了所有这些,希望你能够在你未来的Django项目中开始实施这些知识。