原文:https://blog.csdn.net/zcyuefan/article/details/77743380

1. 需求vs现状

1.1 需求
要求做一个ERP后台辅助管理的程序,有以下几项基本要求:
1. 基本的增删改查功能
2. 基于对象的权限控制(如:系统用户分为平台运营人员和商家用户,商家用户小A只能查看编辑所属商家记录,而管理员可以纵览全局)
3. 数据库记录导入导出(xsl, json等),并且拥有对象级的权限控制(如:小A不能导出小B公司的信息,更不能导入小B公司信息进行更新和新增)

1.2 现状
实现需求1:Django-admin让我们能够很方便的实现一个管理后台程序。django-xadmin则在拥有admin基本功能的基础上增加了更为丰富的功能、界面也更加漂亮。类似还有django-suit等,本文使用xadmin(功能更丰富);
实现需求2:django-admin,以及xadmin都只有基于model级的权限控制机制,需要自己扩展或者使用开源解决方案,如django-guardian,django-rules,本文结合django-rules实现了该功能;
实现需求3:xadmin虽然自带导出功能,但是导入功能没有实现,django自带后台结合django-import-export可以很容易实现,但是xadmin并不直接兼容,只有通过xadmin的插件机制实现。
2. 功能实现
本节主要展示对象级权限功能实现。django工程、xadmin替换原生admin的设置,请参照官方文档。

2.1 安装并配置rules
pip安装:

$ pip install rules
1
配置settings.py

# settings.py
INSTALLED_APPS = (
# ...
'rules',
)
AUTHENTICATION_BACKENDS = (
'rules.permissions.ObjectPermissionBackend',
'django.contrib.auth.backends.ModelBackend',
)

2.2 建立model
新增CompanyUser模型表示商家账户(即对django自带user模块进行扩展,使每个账号绑定自己的公司码),新增Customer模型表示商家的客户信息并包含公司码字段,商家账号只能查看、编辑、导入、导出公司码一致的商家客户信息

# model.py
class CompanyUser(models.Model):
user = models.OneToOneField(User, verbose_name='用户名')
is_taixiang_admin = models.BooleanField('是否运营人员', default=False)
company_code = models.CharField('公司码', max_length=20, blank=True, default='')

def __unicode__(self):
return '%s' % self.user

class Meta:
verbose_name = '导入账号'
verbose_name_plural = verbose_name

class Customer(models.Model):
name = models.CharField('客户姓名', max_length=50)
phone = models.CharField('客户电话', max_length=12)
type_choice = ((1, '普通'), (2, '批发'), (3, 'VIP'))
creator = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='创建人', blank=True, null=True)
company_code = models.CharField('公司码', max_length=20, blank=True, null=True)

def __unicode__(self):
return '%s-%s-%s' % (self.company_code, self.name, self.phone1)

class Meta:
permissions = (
("simulate_import_customer", "允许模拟导入客户"),
("import_customer", "允许导入客户至商家系统"),
)
verbose_name = "客户"
verbose_name_plural = verbose_name

2.2 使用rule
在model统计目录新增rules.py,配置该app相关的对象权限
引用rules

# rules.py
# On Python 2, you must also add the following to the top of your rules.py file, or you'll get import errors trying to import django-rules itself
from __future__ import absolute_import

import rules

# 使用修饰符@rules.predicate自定义predicates(判断),返回True表示有权限,False表示无权限

# Predicates

@rules.predicate
def is_colleague(user, entry):
if not entry or not hasattr(user, 'companyuser'):
return False
return entry.company_code == user.companyuser.company_code

@rules.predicate
def is_taixiang_admin(user):
if not hasattr(user, 'companyuser'):
return False
return user.companyuser.is_taixiang_admin

# predicates间可以进行运算
is_colleague_or_taixiang_admin = is_colleague | is_taixiang_admin | rules.is_superuser

# 设置Rules

rules.add_rule('can_view_customer', is_colleague_or_taixiang_admin)
rules.add_rule('can_delete_customer', is_colleague_or_taixiang_admin)
rules.add_perm('can_change_customer', is_colleague_or_taixiang_admin)

# 设置Permissions

rules.add_perm('data_import.view_customer', is_colleague_or_taixiang_admin)
rules.add_perm('data_import.delete_customer', is_colleague_or_taixiang_admin)
rules.add_perm('data_import.add_customer', is_colleague_or_taixiang_admin)
rules.add_perm('data_import.change_customer', is_colleague_or_taixiang_admin)

2.3 admin.py以及adminx.py设置
如果使用原生的django-admin,admin.py做如下设置:

# admin.py
from __future__ import absolute_import

from django.contrib import admin
from rules.contrib.admin import ObjectPermissionsModelAdmin
from .models import Customer

# ModelAdmin class继承ObjectPermissionsModelAdmin即可
class CustomerAdmin(ObjectPermissionsModelAdmin):
pass

admin.site.register(Customer, CustomerAdmin)

使用xadmin,由于ObjectPermissionsModelAdmin无法直接使用,故参照源码重写has_change_permission和has_delete_permission方法即可。
注意:必须引用rules文件,权限规则才会生效,对于xadmin,添加
from .rules import *即可

# adminx.py
class CustomerAdmin(object):
def has_change_permission(self, obj=None):
codename = get_permission_codename('change', self.opts)
return self.user.has_perm('%s.%s' % (self.app_label, codename), obj)

def has_delete_permission(self, obj=None):
codename = get_permission_codename('delete', self.opts)
return self.user.has_perm('%s.%s' % (self.app_label, codename), obj)

# 重写queryset()或者get_list_display(),list view的权限也做到了对象级隔离
def queryset(self):
qs = super(CustomerAdmin, self).queryset()
if self.request.user.is_superuser or is_taixiang_admin(self.request.user):
return qs
try:
return qs.filter(company_code=self.request.user.companyuser.company_code)
except AttributeError:
return None

class CompanyUserAdmin(object):
pass

xadmin.sites.site.register(Customer, CustomerAdmin)
xadmin.sites.site.register(CompanyUser, CompanyUserAdmin)

---------------------
作者:zcyuefan
来源:CSDN
原文:https://blog.csdn.net/zcyuefan/article/details/77743380
版权声明:转载请附上博文链接!

Django-xadmin+rule对象级权限的实现的更多相关文章

  1. django+xadmin在线教育平台(一)

    大家好,此教程为在慕学网的实战教程Python升级3.6 强力Django+杀手级Xadmin打造在线教育平台的学习笔记,不对望指正! 使用Django+Xadmin打造在线教育平台(Python2, ...

  2. WinForm/MIS项目开发之中按钮级权限实践

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  3. 理解SQL Server中的权限体系(下)----安全对象和权限

    原文:http://www.cnblogs.com/CareySon/archive/2012/04/12/SQL-Security-SecurableAndPermission.html 在开始阅读 ...

  4. Django+xadmin打造在线教育平台(二)

    三.xadmin后台管理 3.1.xadmin的安装 django2.0的安装(源码安装方式): https://github.com/sshwsfc/xadmin/tree/django2 把zip ...

  5. Django+xadmin打造在线教育平台(三)

    五.完成注册.找回密码和激活验证码功能 5.1.用户注册 register.html拷贝到templates目录 (1)users/views.py class RegisterView(View): ...

  6. Chapter 3 Protecting the Data(2):分配列级权限

    原文出处:http://blog.csdn.net/dba_huangzj/article/details/39577861,专题目录:http://blog.csdn.net/dba_huangzj ...

  7. 第四百零二节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署,uwsgi安装和启动,nginx的安装与启动,uwsgi与nginx的配置文件+虚拟主机配置

    第四百零二节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署,uwsgi安装和启动,nginx的安装与启动,uwsgi与nginx的配置文件+虚拟主机配置 软件版本  uwsgi- ...

  8. 第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6

    第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6 1.检测系统是否已经安装过mysql或其依赖,若已装过要先将其删除,否则第4步 ...

  9. 第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件

    第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件 设置后台列表页面字段统计 在当前APP里的adminx.py文件里的数据表管理器里设置 ag ...

随机推荐

  1. HDU2899 Strange fuction 【二分】

    Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  2. 用MJExtension简化MVC

    首先引入MJExtension框架 模型 #import <Foundation/Foundation.h> @interface FundsModel : NSObject /** * ...

  3. Android休眠唤醒机制简介(一)【转】

    本文转载自:http://blog.csdn.net/zhaoxiaoqiang10_/article/details/24408129 Android休眠唤醒机制简介(一) ************ ...

  4. C++_class_powerpoint_1.2

    用英文编写(复制黏贴)果然比较吃力啊,果然还是要写中文. Expressions and Statements Operator summary Scope resolution   class::m ...

  5. java-com-util-common-service:BaseService.java

    ylbtech-java-com-util-common-service:BaseService.java 1.返回顶部 1. package com.shineyoo.manager.util.co ...

  6. 原生JS---4

    原生js学习笔记4——BOM操作 什么是DOM DOM:Do 1. js的组成部分 2. 一套标准,目前有DOM1和DOM2这两种标准 我们可以使用DOM操作来操作页面中的元素. DOM节点 子节点 ...

  7. Django day15 (二) csrf的 跨站请求伪造 与 局部禁用 , 局部使用

    一:  csrf 的跨站请求伪造 二: csrf 的局部禁用 , 局部使用

  8. linux ssh文件输

    在linux下一般用scp这个命令来通过ssh传输文件. 1.从服务器上下载文件scp username@servername:/path/filename /var/www/local_dir(本地 ...

  9. invoke与call

    “调用一个委托实例” 中的 “调用” 对应的是invoke,理解为 “唤出” 更恰当.它和后面的 “在一个对象上调用方法” 中的 “调用” 稍有不同,后则对应的是call.在英语的语境中,invoke ...

  10. elasticsearch5.3.0 bulk index 性能调优实践

    elasticsearch5.3.0 bulk index 性能调优实践 通俗易懂