1. Overview of the Django permissions mechanism
The permission mechanism can restrain the user behavior, control the display content of the page, make the API more secure and flexible, and use the privilege mechanism to make the system more powerful and robust. Therefore, it is very necessary to clarify the Django permission mechanism based on Django development.
1.1 Django's permissions control
Django completes the privilege mechanism with user, group, and permission, which assigns a permission that belongs to the model to the user or group, which can be understood as a global permission. That is, if user A has writable permissions to the data Model B, a can modify all instances of Model B (objects). The same is true for group permissions, and all instances of Model B can be modified by all users who belong to group C if you give the writable permission to model B for Group C.
This kind of permission mechanism can only solve some simple application requirements, and most of the scenarios require a more granular permission mechanism. For example, blog system users can be divided into "administrator", "editor", "author" and "Reader" four user groups; Blog system administrators and editors have permission to view, modify, and delete all articles, and authors can only modify and delete their own written articles, while the reader only has access to read. Administrator, editor and Reader permissions, we can use global permissions to control, and for the author, the global permissions can not meet the requirements, only through the global permissions, or allow the author to edit the article does not belong to the author, or even his own article can not be modified.
In the above scenario, the Django-brought permission mechanism does not meet the requirements and needs to introduce another finer permission mechanism: 对象权限(object permission)
.
Object permission is a permission mechanism on the granularity of objects that allows authorization for each specific object. Still follow the first example, if model B has three instances b1,b2 and B3, if we give B1 the writable permission to user A, then a can modify the B1 object, and the B2,B3 cannot be modified. For group, as well, if B2 's writable permission is given to group C, all users who belong to group C can modify B2, but cannot modify B1 and B3. Combining with Django's own permission mechanism and object permission, the author's permission control in the blog system is solved: the author is not allowed to edit the article globally, but for the specific articles belonging to the author, give the editor permission.
Django actually contains the framework of object permission, but without a specific implementation, the implementation of object permission requires the use of third-party app Django-guardian, which we call Django in development Guradian package is a good method.
1.2 Django's Permission entries
Django stores permission entries with permission objects, each of which has three permission, the Add model, the change model, and the delete model by default. For example, when you define a car named "Car", the corresponding three permission are automatically created: add_car
, change_car
and delete_car
. Django also allows custom permission, for example, we can create a new permission entry for car: drive_car
, clean_car
, and fix_car
so on
It is important to note that permission always corresponds to model, and if an object is not an instance of model, we cannot create/assign permissions for it.
2. The application of Django's own privilege mechanism 2.1 Permission
As mentioned above, after the Django defines each model, the Add, change, and delete three permission of the model are added by default, and the custom permission can be added manually when we define the model:
class Task(models.Model): ... class Meta: permissions = ( ("view_task", "Can see available tasks"), ("change_task_status", "Can change the status of tasks"), ("close_task", "Can remove a task by setting its status as closed"), )
Each permission is an django.contrib.auth.Permission
instance of a type that contains three fields name
, and which codename
content_type
content_type
reflects what model the permission belongs to, codename
such as the one above view_task
, which is used to check permissions in the code logic. name
is a description of permission, the default display when printing permission to a screen or page isname
Creating custom permissions in model, from a system development perspective, is understood to create built-in permissions for the system, if the requirements involve creating custom permissions when the user uses the system, use the following method:
from myapp.models import BlogPostfrom django.contrib.auth.models import Permissionfrom django.contrib.contenttypes.models import ContentTypecontent_type = ContentType.objects.get_for_model(BlogPost)permission = Permission.objects.create(codename=‘can_publish‘, name=‘Can Publish Posts‘, content_type=content_type)
2.2 User Permission Management
The User_permission field of the user object manages permissions for users:
#增加权限myuser.user_permissions.remove(permission, permission, ...) #删除权限myuser.user_permissions.clear() #清空权限############################################################### 注:上面的permission为django.contrib.auth.Permission类型的实例##############################################################
To check the user rights, use the has_perm()
method:
myuser.has_perm(‘myapp.fix_car‘)
has_perm()
The parameter of the method is permission, codename
but the parameter is passed with the prefix of the app that the model belongs to, in the format <app label>.<permission codename>
.
Whether the permission is given to user or group, the has_perm()
method applies
Note:
user.get_all_permissions()
The permission method lists all permissions for the user, and the return value is a list of the name
user.get_group_permissions()
The permission method lists the permissions of the group to which the user belongs, and the return value is a list of name
2.3 Group Permission Management
The group permission management logic is consistent with user permission management, and the group uses the permissions field for Rights Management:
group.permissions = [permission_list]group.permissions.add(permission, permission, ...)group.permissions.remove(permission, permission, ...)group.permissions.clear()
Permission checks:
Still use the user.has_perm()
method.
2.4
permission_required
Decorative Device
Permissions can constrain user behavior, and when a permission check is involved in the business logic, decorator is able to separate permissions validation and core business logic, making the code more concise and logically clearer. The decorator of permission is permission_required
:
from django.contrib.auth.decorators import permission_required@permission_required(‘car.drive_car‘)def my_view(request): ...
Permission checks in the 2.5 template
The template uses global variables to perms
store all permissions for the current user, and permission checks can refer to the following example:
{% if perms.main.add_page%}<Liclass="Dropdown" ><Ahref="#"class="Dropdown-toggle"data-toggle="Dropdown"role="Button"Aria-expanded="False" >pages<Spanclass="Caret" ></Span></A><Ulclass="Dropdown-menu"role="Menu" ><Li><Ahref="{% url ' main:admin_pages '%}" >all pages</A></li> <li> <a href= "{% url ' main:admin_page '%}" >new page</a></ li> <li> <a href= "{% url ' main:admin_pages '%} ? draft=true ">drafts</a></< Span class= "Hljs-name" >li> </ul> </li>{% endif%}
3. Application of object permission based on Django-guardian
Django-guardian has extended Django's permissions mechanism based on Django's native logic, and after applying Django-guardian, you can check global permissions using the methods provided by Django-guardian and the native methods of Django. The object permission mechanism provided by Django-guardian makes Django's permissions mechanism more sophisticated.
Django-guardian the detailed use of the documentation, please refer to the official documentation, its object permission common methods are as follows:
from guardian.shortcuts import assign_perm, get_permsfrom guardian.core import ObjectPermissionCheckerfrom guardian.decorators import permission_required
3.1 Adding an object permission
Add the object permission use assign_perm()
method, such as adding Drive_car permissions to the Mycar object for the user:
assign_perm(‘myapp.drive_car‘, request.user, mycar)
assign_perm()
Method can also be used for group
assign_perm(‘myapp.drive_car‘, mygroup, mycar)
3.2 Permission Check 3.2.1 Global permission
get_perms()
The permission method is used to check the user's "Global permissions", as in the same way user.has_perm()
as:
############################## It works! ############################# if Not ' main.change_post ' in get_perms (Request.user, Post): raise HttpResponse ( ' Forbidden ') ###### ######################## It works, too! #############################if Not Request.user.has_perm ( ' main.change_post ') return HttpResponse ( ' Forbidden ')
In the example, although the post object is passed as a parameter to the Get_perms () method, it only checks the user's global permissions for main.change_post
permission, in many cases user.has_perm
, the native substitution, but both user and group can be used as an get_perms()
incoming parameter. In some cases, you can make your code more concise.
3.2.2 Object Permission
Django-guardian uses ObjectPermissionChecker
the object permission to check the user, as shown in the following example:
checker = ObjectPermissionChecker(request.user)print checker.has_perm(‘main.change_post‘, post)
3.3 permission_required Decorator
guardian.decorators.permission_required
Is the decorator of the Django-guardian permission check, which checks both the global permissions and the object permissions (Objects permission), where the accept_global_perms
parameters indicate whether to check the user's global permission, such as:
From Guardian.decoratorsImport permission_requiredClassdeletepost (View): @method_decorator ( Permission_required (' Main.delete_post ', (models). Post, ' id ', ' PK '), accept_global_perms= true)) def get try:pk = Int (PK) Cur_post = models. Post.objects.get (pk=pk) is_draft = cur_post.is_draft url = reverse ( ' main:admin_posts ') Span class= "Hljs-keyword" >if is_draft:url = ' {0}?draft=true '. Format (URL) cur_post.delete ( ) except models. Post.doesnotexist: raise Http404 return redirect (URL)
Note:
A section in decorator that (models.Post, ‘id‘, ‘pk‘)
specifies an object instance, and if this argument is omitted, the global permission is only checked regardless of whether the accept_global_perms value is true or false.
4. Conclusion
Django Native provides a simple global permission control mechanism, but in many scenarios, object permissions (Objects permission) are more useful; Django-guardian is currently a more active Django Extension provides an effective object permission control mechanism, which is recommended for use with the Django native mechanism same strain.
Gevin
Links: https://www.jianshu.com/p/01126437e8a4
Source: Pinterest
The copyright of the book is owned by the author, and any form of reprint should be contacted by the author for authorization and attribution.
Django Permissions mechanism