├── .gitignore
├── Permisson
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
├── app01
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── static
│ └── jquery-3.2.1.js
├── tests.py
└── views.py
├── db.sqlite3
├── manage.py
├── rbac
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── middleware
│ └── rbac.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20170921_1500.py
│ └── __init__.py
├── models.py
├── service
│ └── init_permission.py
├── style_script
│ ├── rbac.css
│ └── rbac.js
├── templates
│ └── rbac
│ │ ├── common_edit.html
│ │ ├── index.html
│ │ ├── menus.html
│ │ ├── permissions.html
│ │ ├── roles.html
│ │ └── users.html
├── templatetags
│ └── custom_tag.py
├── tests.py
├── urls.py
└── views.py
└── templates
├── index.html
└── login.html
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | .static_storage/
56 | .media/
57 | local_settings.py
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
--------------------------------------------------------------------------------
/Permisson/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/Permisson/__init__.py
--------------------------------------------------------------------------------
/Permisson/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for Permisson project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.11.4.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.11/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 's2#(zr+2@y+2nz*a@q)txe+jjvol^x$z0j74e9yx!zb8&33u3u'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 | # DEBUG = False
28 |
29 | ALLOWED_HOSTS = ['*']
30 |
31 |
32 | # Application definition
33 |
34 | INSTALLED_APPS = [
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | 'app01.apps.App01Config',
42 | 'rbac.apps.RbacConfig'
43 | ]
44 |
45 | MIDDLEWARE = [
46 | 'django.middleware.security.SecurityMiddleware',
47 | 'django.contrib.sessions.middleware.SessionMiddleware',
48 | 'django.middleware.common.CommonMiddleware',
49 | 'django.middleware.csrf.CsrfViewMiddleware',
50 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
51 | 'django.contrib.messages.middleware.MessageMiddleware',
52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
53 | 'rbac.middleware.rbac.RbacMiddleware'
54 | ]
55 |
56 | ROOT_URLCONF = 'Permisson.urls'
57 |
58 | TEMPLATES = [
59 | {
60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
61 | 'DIRS': [os.path.join(BASE_DIR, 'templates')]
62 | ,
63 | 'APP_DIRS': True,
64 | 'OPTIONS': {
65 | 'context_processors': [
66 | 'django.template.context_processors.debug',
67 | 'django.template.context_processors.request',
68 | 'django.contrib.auth.context_processors.auth',
69 | 'django.contrib.messages.context_processors.messages',
70 | ],
71 | },
72 | },
73 | ]
74 |
75 | WSGI_APPLICATION = 'Permisson.wsgi.application'
76 |
77 |
78 | # Database
79 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
80 |
81 | DATABASES = {
82 | 'default': {
83 | 'ENGINE': 'django.db.backends.sqlite3',
84 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
85 | }
86 | }
87 |
88 |
89 | # Password validation
90 | # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
91 |
92 | AUTH_PASSWORD_VALIDATORS = [
93 | {
94 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
95 | },
96 | {
97 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
98 | },
99 | {
100 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
101 | },
102 | {
103 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
104 | },
105 | ]
106 |
107 |
108 | # Internationalization
109 | # https://docs.djangoproject.com/en/1.11/topics/i18n/
110 |
111 | LANGUAGE_CODE = 'en-us'
112 |
113 | TIME_ZONE = 'UTC'
114 |
115 | USE_I18N = True
116 |
117 | USE_L10N = True
118 |
119 | USE_TZ = True
120 |
121 |
122 | # Static files (CSS, JavaScript, Images)
123 | # https://docs.djangoproject.com/en/1.11/howto/static-files/
124 |
125 | STATIC_URL = '/static/'
126 | STATIC_ROOT = (
127 | os.path.join(BASE_DIR, '/app01/static'),
128 | )
129 |
130 | # 定义session 键:
131 | # 保存用户权限url列表
132 | # 保存 权限菜单 和所有 菜单
133 | SESSION_PERMISSION_URL_KEY = 'cool'
134 |
135 | SESSION_MENU_KEY = 'awesome'
136 | ALL_MENU_KEY = 'k1'
137 | PERMISSION_MENU_KEY = 'k2'
138 |
139 | LOGIN_URL = '/login/'
140 |
141 | REGEX_URL = r'^{url}$' # url作严格匹配
142 |
143 | # 配置url权限白名单
144 | SAFE_URL = [
145 | r'/login/',
146 | '/admin/.*',
147 | '/test/',
148 | '/index/',
149 | '^/rbac/',
150 | ]
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/Permisson/urls.py:
--------------------------------------------------------------------------------
1 | """Permisson URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import url, include
17 | from django.contrib import admin
18 | from app01 import views
19 |
20 | urlpatterns = [
21 | url(r'^admin/', admin.site.urls),
22 | url(r'^login/$', views.login),
23 | url(r'^test/$', views.test),
24 | url(r'^index/$', views.index),
25 | url(r'^order/$', views.index),
26 | url(r'^survey/produce/$', views.index),
27 | url(r'^stock/detail/$', views.index),
28 | url(r'^produce/detail/$', views.index),
29 | url(r'^rbac/', include('rbac.urls') )
30 | ]
31 |
--------------------------------------------------------------------------------
/Permisson/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for Permisson project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Permisson.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/app01/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/app01/__init__.py
--------------------------------------------------------------------------------
/app01/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/app01/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class App01Config(AppConfig):
5 | name = 'app01'
6 |
--------------------------------------------------------------------------------
/app01/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/app01/migrations/__init__.py
--------------------------------------------------------------------------------
/app01/models.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/app01/models.py
--------------------------------------------------------------------------------
/app01/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/app01/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect, HttpResponse
2 | from rbac.models import UserInfo
3 | from rbac.service.init_permission import init_permission
4 | from django.conf import settings
5 |
6 |
7 | def login(request):
8 | if request.method == "GET":
9 | return render(request, "login.html")
10 | else:
11 | username = request.POST.get('username')
12 | password = request.POST.get('password')
13 | user_obj = UserInfo.objects.filter(username=username, password=password).first()
14 | if not user_obj:
15 | return render(request, "login.html", {'error': '用户名或密码错误!'})
16 | else:
17 | init_permission(request, user_obj)
18 | return redirect('/index/')
19 |
20 |
21 | def index(request):
22 |
23 | return render(request, 'index.html')
24 |
25 |
26 | def test(request):
27 | # 前端请求过来,首页显示多级菜单
28 | # 请求过来,拿到session中的信息,拿到菜单,权限数据 -- 定制数据结构 -- 作显示
29 | menu = request.session[settings.SESSION_MENU_KEY]
30 | all_menu = menu[settings.ALL_MENU_KEY]
31 | permission_url = menu[settings.PERMISSION_MENU_KEY]
32 |
33 | print(all_menu)
34 | print('-----------')
35 | print(permission_url)
36 |
37 | all_menu = [
38 | {'id': 1, 'title': '订单管理', 'parent_id': None}, {'id': 2, 'title': '库存管理', 'parent_id': None},
39 | {'id': 3, 'title': '生产管理', 'parent_id': None}, {'id': 4, 'title': '生产调查', 'parent_id': None}
40 | ]
41 |
42 | # 定制数据结构
43 | all_menu_dict = {}
44 | for item in all_menu:
45 | item['status'] = False
46 | item['open'] = False
47 | item['children'] = []
48 | all_menu_dict[item['id']] = item
49 |
50 | all_menu_dict = {
51 | 1: {'id': 1, 'title': '订单管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
52 | 2: {'id': 2, 'title': '库存管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
53 | 3: {'id': 3, 'title': '生产管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
54 | 4: {'id': 4, 'title': '生产调查', 'parent_id': None, 'status': False, 'open': False, 'children': []}
55 | }
56 |
57 | permission_url = [
58 | {'title': '查看订单', 'url': '/order', 'menu_id': 1},
59 | {'title': '查看库存清单', 'url': '/stock/detail', 'menu_id': 2},
60 | {'title': '查看生产订单', 'url': '/produce/detail', 'menu_id': 3},
61 | {'title': '产出管理', 'url': '/survey/produce', 'menu_id': 4},
62 | {'title': '工时管理', 'url': '/survey/labor', 'menu_id': 4},
63 | {'title': '入库', 'url': '/stock/in', 'menu_id': 2},
64 | {'title': '排单', 'url': '/produce/new', 'menu_id': 3}
65 | ]
66 |
67 | request_rul = '/stock/in'
68 | import re
69 |
70 | for url in permission_url:
71 | # 添加两个状态:显示 和 展开
72 | url['status'] = True
73 | pattern = url['url']
74 | if re.match(pattern, request_rul):
75 | url['open'] = True
76 | else:
77 | url['open'] = False
78 |
79 | # 将url添加到菜单下
80 | all_menu_dict[url['menu_id']]["children"].append(url)
81 |
82 | # 显示菜单:url 的菜单及上层菜单 status: true
83 | pid = url['menu_id']
84 | while pid:
85 | all_menu_dict[pid]['status'] = True
86 | pid = all_menu_dict[pid]['parent_id']
87 |
88 | # 展开url上层菜单:url['open'] = True, 其菜单及其父菜单open = True
89 | if url['open']:
90 | ppid = url['menu_id']
91 | while ppid:
92 | all_menu_dict[ppid]['open'] = True
93 | ppid = all_menu_dict[ppid]['parent_id']
94 |
95 | # 整理菜单层级结构:没有parent_id 的为根菜单, 并将有parent_id 的菜单项加入其父项的chidren内
96 | final_menu = []
97 | for i in all_menu_dict:
98 | if all_menu_dict[i]['parent_id']:
99 | pid = all_menu_dict[i]['parent_id']
100 | parent_menu = all_menu_dict[pid]
101 | parent_menu['children'].append(all_menu_dict[i])
102 | else:
103 | final_menu.append(all_menu_dict[i])
104 |
105 | print('final_menu ---------------\n',final_menu)
106 |
107 |
108 | return HttpResponse('...')
109 |
--------------------------------------------------------------------------------
/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/db.sqlite3
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Permisson.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError:
10 | # The above import may fail for some other reason. Ensure that the
11 | # issue is really that Django is missing to avoid masking other
12 | # exceptions on Python 2.
13 | try:
14 | import django
15 | except ImportError:
16 | raise ImportError(
17 | "Couldn't import Django. Are you sure it's installed and "
18 | "available on your PYTHONPATH environment variable? Did you "
19 | "forget to activate a virtual environment?"
20 | )
21 | raise
22 | execute_from_command_line(sys.argv)
23 |
--------------------------------------------------------------------------------
/rbac/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/rbac/__init__.py
--------------------------------------------------------------------------------
/rbac/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Menu, Permission, Role, UserInfo
3 |
4 | # Register your models here.
5 | admin.site.register(Menu)
6 | admin.site.register(Permission)
7 | admin.site.register(Role)
8 | admin.site.register(UserInfo)
--------------------------------------------------------------------------------
/rbac/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class RbacConfig(AppConfig):
5 | name = 'rbac'
6 |
--------------------------------------------------------------------------------
/rbac/forms.py:
--------------------------------------------------------------------------------
1 | from django.forms import ModelForm
2 | from .models import UserInfo, Role, Permission, Menu
3 |
4 |
5 | class UserInfoModelForm(ModelForm):
6 | class Meta:
7 | model = UserInfo
8 | fields = '__all__'
9 | labels = {
10 | 'username': '用户名',
11 | 'password': '密码',
12 | 'nickname': '昵称',
13 | 'email': '邮箱',
14 | 'roles': '角色',
15 | }
16 |
17 |
18 | class RoleModelForm(ModelForm):
19 | class Meta:
20 | model = Role
21 | fields = '__all__'
22 | labels = {
23 | 'title': '角色',
24 | 'permissions': '权限',
25 | }
26 |
27 |
28 | class PermissionModelForm(ModelForm):
29 | class Meta:
30 | model = Permission
31 | fields = '__all__'
32 | labels = {
33 | 'title': '权限',
34 | 'url': 'url',
35 | 'menu': '所属菜单'
36 | }
37 |
38 |
39 | class MenuModelForm(ModelForm):
40 | class Meta:
41 | model = Menu
42 | fields = '__all__'
43 | labels = {
44 | 'title': '菜单',
45 | 'parent': '父级菜单',
46 | }
47 |
--------------------------------------------------------------------------------
/rbac/middleware/rbac.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.shortcuts import HttpResponse, redirect
3 | import re
4 |
5 |
6 | class MiddlewareMixin(object):
7 | def __init__(self, get_response=None):
8 | self.get_response = get_response
9 | super(MiddlewareMixin, self).__init__()
10 |
11 | def __call__(self, request):
12 | response = None
13 | if hasattr(self, 'process_request'):
14 | response = self.process_request(request)
15 | if not response:
16 | response = self.get_response(request)
17 | if hasattr(self, 'process_response'):
18 | response = self.process_response(request, response)
19 | return response
20 |
21 |
22 | class RbacMiddleware(MiddlewareMixin):
23 | """
24 | 检查用户的url请求是否是其权限范围内
25 | """
26 | def process_request(self, request):
27 | request_url = request.path_info
28 | permission_url = request.session.get(settings.SESSION_PERMISSION_URL_KEY)
29 | print('访问url',request_url)
30 | print('权限--',permission_url)
31 | # 如果请求url在白名单,放行
32 | for url in settings.SAFE_URL:
33 | if re.match(url, request_url):
34 | return None
35 |
36 | # 如果未取到permission_url, 重定向至登录;为了可移植性,将登录url写入配置
37 | # 另外,Login必须设置白名单,否则访问login会反复重定向
38 | if not permission_url:
39 | return redirect(settings.LOGIN_URL)
40 |
41 | # 循环permission_url,作为正则,匹配用户request_url
42 | # 正则应该进行一些限定,以处理:/user/ -- /user/add/匹配成功的情况
43 | flag = False
44 | for url in permission_url:
45 | url_pattern = settings.REGEX_URL.format(url=url)
46 | if re.match(url_pattern, request_url):
47 | flag = True
48 | break
49 | if flag:
50 | return None
51 | else:
52 | # 如果是调试模式,显示可访问url
53 | if settings.DEBUG:
54 | info ='
' + ( '
'.join(permission_url))
55 | return HttpResponse('无权限,请尝试访问以下地址:%s' %info)
56 | else:
57 | return HttpResponse('无权限访问')
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/rbac/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.4 on 2017-09-21 05:10
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | initial = True
12 |
13 | dependencies = [
14 | ]
15 |
16 | operations = [
17 | migrations.CreateModel(
18 | name='Menu',
19 | fields=[
20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21 | ('title', models.CharField(max_length=32, unique=True)),
22 | ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='rbac.Menu')),
23 | ],
24 | ),
25 | migrations.CreateModel(
26 | name='Permission',
27 | fields=[
28 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29 | ('title', models.CharField(max_length=32, unique=True)),
30 | ('url', models.CharField(max_length=128, unique=True)),
31 | ('menu', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='rbac.Menu')),
32 | ],
33 | ),
34 | migrations.CreateModel(
35 | name='Role',
36 | fields=[
37 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
38 | ('title', models.CharField(max_length=32, unique=True)),
39 | ('permissions', models.ManyToManyField(to='rbac.Permission')),
40 | ],
41 | ),
42 | migrations.CreateModel(
43 | name='UserInfo',
44 | fields=[
45 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
46 | ('username', models.CharField(max_length=32)),
47 | ('password', models.CharField(max_length=64)),
48 | ('nickname', models.CharField(max_length=32)),
49 | ('email', models.EmailField(max_length=254)),
50 | ('role', models.ManyToManyField(to='rbac.Role')),
51 | ],
52 | ),
53 | ]
54 |
--------------------------------------------------------------------------------
/rbac/migrations/0002_auto_20170921_1500.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.4 on 2017-09-21 07:00
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('rbac', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.RenameField(
16 | model_name='userinfo',
17 | old_name='role',
18 | new_name='roles',
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/rbac/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayhan-Huang/RBAC/fad0a56ca4d0f45cb9354c050364b6d017bf67fc/rbac/migrations/__init__.py
--------------------------------------------------------------------------------
/rbac/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Menu(models.Model):
5 | """
6 | 菜单
7 | """
8 | title = models.CharField(max_length=32, unique=True)
9 | parent = models.ForeignKey("Menu", null=True, blank=True)
10 | # 定义菜单间的自引用关系
11 | # 权限url 在 菜单下;菜单可以有父级菜单;还要支持用户创建菜单,因此需要定义parent字段(parent_id)
12 | # blank=True 意味着在后台管理中填写可以为空,根菜单没有父级菜单
13 |
14 | def __str__(self):
15 | # 显示层级菜单
16 | title_list = [self.title]
17 | p = self.parent
18 | while p:
19 | title_list.insert(0, p.title)
20 | p = p.parent
21 | return '-'.join(title_list)
22 |
23 |
24 | class Permission(models.Model):
25 | """
26 | 权限
27 | """
28 | title = models.CharField(max_length=32, unique=True)
29 | url = models.CharField(max_length=128, unique=True)
30 | menu = models.ForeignKey("Menu", null=True, blank=True)
31 |
32 | def __str__(self):
33 | # 显示带菜单前缀的权限
34 | return '{menu}---{permission}'.format(menu=self.menu, permission=self.title)
35 |
36 |
37 | class Role(models.Model):
38 | """
39 | 角色:绑定权限
40 | """
41 | title = models.CharField(max_length=32, unique=True)
42 |
43 | permissions = models.ManyToManyField("Permission")
44 | # 定义角色和权限的多对多关系
45 |
46 | def __str__(self):
47 | return self.title
48 |
49 |
50 | class UserInfo(models.Model):
51 | """
52 | 用户:划分角色
53 | """
54 | username = models.CharField(max_length=32)
55 | password = models.CharField(max_length=64)
56 | nickname = models.CharField(max_length=32)
57 | email = models.EmailField()
58 |
59 | roles = models.ManyToManyField("Role")
60 | # 定义用户和角色的多对多关系
61 |
62 | def __str__(self):
63 | return self.nickname
64 |
65 |
66 | ''' 继承自带的用户表
67 |
68 | settings.py:
69 | AUTH_USER_MODEL = 'rbac.User'
70 |
71 | from django.contrib.auth.models import AbstractUser
72 |
73 | class User(AbstractUser):
74 | """
75 | 用户:划分角色
76 | """
77 | username = models.CharField(verbose_name='用户', max_length=32, unique=True)
78 |
79 | roles = models.ManyToManyField(verbose_name='角色', to="Role")
80 | # 定义用户和角色的多对多关系
81 |
82 | def __str__(self):
83 | return self.username
84 |
85 | '''
86 |
87 |
88 |
--------------------------------------------------------------------------------
/rbac/service/init_permission.py:
--------------------------------------------------------------------------------
1 | from ..models import UserInfo, Menu
2 |
3 |
4 | def init_permission(request, user_obj):
5 | """
6 | 初始化用户权限, 写入session
7 | :param request:
8 | :param user_obj:
9 | :return:
10 | """
11 | permission_item_list = user_obj.roles.values('permissions__url',
12 | 'permissions__title',
13 | 'permissions__menu_id').distinct()
14 | # print(permission_menu_list)
15 | permission_url_list = [] # 用户权限url列表,--> 用于中间件验证用户权限
16 | permission_menu_list = [] # 用户权限url所属菜单列表 [{"title":xxx, "url":xxx, "menu_id": xxx},{},]
17 |
18 | for item in permission_item_list:
19 | permission_url_list.append(item['permissions__url'])
20 | if item['permissions__menu_id']:
21 | temp = {"title": item['permissions__title'],
22 | "url": item["permissions__url"],
23 | "menu_id": item["permissions__menu_id"]}
24 | permission_menu_list.append(temp)
25 |
26 | menu_list = list(Menu.objects.values('id', 'title', 'parent_id'))
27 | # 注:session在存储时,会先对数据进行序列化,因此对于Queryset对象写入session, 加list()转为可序列化对象
28 |
29 | from django.conf import settings
30 |
31 | # 保存用户权限url列表
32 | print('permission_url_list ------------------- ',permission_url_list)
33 | print('permission_menu_list ------------------- ',permission_menu_list)
34 | print('menu_list ------------------- ',menu_list)
35 |
36 | request.session[settings.SESSION_PERMISSION_URL_KEY] = permission_url_list
37 |
38 | # 保存 权限菜单 和所有 菜单
39 | request.session[settings.SESSION_MENU_KEY] = {
40 | settings.ALL_MENU_KEY: menu_list,
41 | settings.PERMISSION_MENU_KEY: permission_menu_list,
42 | }
43 |
44 | print('request.session[settings.SESSION_PERMISSION_URL_KEY] ------------------- ', request.session[settings.SESSION_PERMISSION_URL_KEY])
45 |
--------------------------------------------------------------------------------
/rbac/style_script/rbac.css:
--------------------------------------------------------------------------------
1 |
2 | .rbac-hide {
3 | display: none;
4 | }
5 |
6 | .rbac-menu-item .rbac-menu-body {
7 | margin-left: 20px;
8 | }
9 |
10 | .rbac-menu-body a {
11 | display: block;
12 | }
13 |
14 | .rbac-menu-body a.rbac-active {
15 | color: red;
16 | }
17 |
--------------------------------------------------------------------------------
/rbac/style_script/rbac.js:
--------------------------------------------------------------------------------
1 | $('.rbac-menu-header').click(function () {
2 | $(this).next().toggleClass('rbac-hide');
3 | //$(this).next().removeClass('rbac-hide').parent().siblings().find('.rbac-menu-body').addClass('rbac-hide');
4 | });
--------------------------------------------------------------------------------
/rbac/templates/rbac/common_edit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 | {{ title }}
9 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/rbac/templates/rbac/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 | 菜单管理
10 | 角色管理
11 | 权限管理
12 | 用户管理
13 |
14 |
15 |
--------------------------------------------------------------------------------
/rbac/templates/rbac/menus.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
11 |
12 | 菜单 |
13 | 父级菜单 |
14 | 操作 |
15 |
16 | {% for menu in menu_list %}
17 |
18 | {{ menu.title }} |
19 | {{ menu.parent }} |
20 | 编辑 |
21 | 删除 |
22 |
23 | {% endfor %}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/rbac/templates/rbac/permissions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
11 |
12 | 权限 |
13 | url |
14 | 所属菜单 |
15 | 操作 |
16 |
17 | {% for permission in permission_list %}
18 |
19 | {{ permission.title }} |
20 | {{ permission.url }} |
21 | {{ permission.menu }} |
22 | 编辑 |
23 | 删除 |
24 |
25 | {% endfor %}
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/rbac/templates/rbac/roles.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
11 |
12 | 角色 |
13 | 权限 |
14 | 操作 |
15 |
16 | {% for role in role_list %}
17 |
18 | {{ role.title }} |
19 | {{ role.permissions.all }} |
20 | 编辑 |
21 | 删除 |
22 |
23 | {% endfor %}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/rbac/templates/rbac/users.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
11 |
12 | 用户名 |
13 | 密码 |
14 | 昵称 |
15 | 邮件 |
16 | 角色 |
17 | 操作 |
18 |
19 | {% for user in user_list %}
20 |
21 | {{ user.username }} |
22 | {{ user.password }} |
23 | {{ user.nickname }} |
24 | {{ user.email }} |
25 | {{ user.roles.all }} |
26 | 编辑 |
27 | 删除 |
28 |
29 | {% endfor %}
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/rbac/templatetags/custom_tag.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.conf import settings
3 | import re, os
4 | from django.utils.safestring import mark_safe
5 |
6 | register = template.Library()
7 |
8 |
9 | def get_structure_data(request):
10 | """处理菜单结构"""
11 | menu = request.session[settings.SESSION_MENU_KEY]
12 | all_menu = menu[settings.ALL_MENU_KEY]
13 | permission_url = menu[settings.PERMISSION_MENU_KEY]
14 |
15 | # all_menu = [
16 | # {'id': 1, 'title': '订单管理', 'parent_id': None},
17 | # {'id': 2, 'title': '库存管理', 'parent_id': None},
18 | # {'id': 3, 'title': '生产管理', 'parent_id': None},
19 | # {'id': 4, 'title': '生产调查', 'parent_id': None}
20 | # ]
21 |
22 | # 定制数据结构
23 | all_menu_dict = {}
24 | for item in all_menu:
25 | item['status'] = False
26 | item['open'] = False
27 | item['children'] = []
28 | all_menu_dict[item['id']] = item
29 |
30 | # all_menu_dict = {
31 | # 1: {'id': 1, 'title': '订单管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
32 | # 2: {'id': 2, 'title': '库存管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
33 | # 3: {'id': 3, 'title': '生产管理', 'parent_id': None, 'status': False, 'open': False, 'children': []},
34 | # 4: {'id': 4, 'title': '生产调查', 'parent_id': None, 'status': False, 'open': False, 'children': []}
35 | # }
36 |
37 | # permission_url = [
38 | # {'title': '查看订单', 'url': '/order', 'menu_id': 1},
39 | # {'title': '查看库存清单', 'url': '/stock/detail', 'menu_id': 2},
40 | # {'title': '查看生产订单', 'url': '/produce/detail', 'menu_id': 3},
41 | # {'title': '产出管理', 'url': '/survey/produce', 'menu_id': 4},
42 | # {'title': '工时管理', 'url': '/survey/labor', 'menu_id': 4},
43 | # {'title': '入库', 'url': '/stock/in', 'menu_id': 2},
44 | # {'title': '排单', 'url': '/produce/new', 'menu_id': 3}
45 | # ]
46 |
47 | request_rul = request.path_info
48 |
49 | for url in permission_url:
50 | # 添加两个状态:显示 和 展开
51 | url['status'] = True
52 | pattern = url['url']
53 | if re.match(pattern, request_rul):
54 | url['open'] = True
55 | else:
56 | url['open'] = False
57 |
58 | # 将url添加到菜单下
59 | all_menu_dict[url['menu_id']]["children"].append(url)
60 |
61 | # 显示菜单:url 的菜单及上层菜单 status: true
62 | pid = url['menu_id']
63 | while pid:
64 | all_menu_dict[pid]['status'] = True
65 | pid = all_menu_dict[pid]['parent_id']
66 |
67 | # 展开url上层菜单:url['open'] = True, 其菜单及其父菜单open = True
68 | if url['open']:
69 | ppid = url['menu_id']
70 | while ppid:
71 | all_menu_dict[ppid]['open'] = True
72 | ppid = all_menu_dict[ppid]['parent_id']
73 |
74 | # 整理菜单层级结构:没有parent_id 的为根菜单, 并将有parent_id 的菜单项加入其父项的chidren内
75 | menu_data = []
76 | for i in all_menu_dict:
77 | if all_menu_dict[i]['parent_id']:
78 | pid = all_menu_dict[i]['parent_id']
79 | parent_menu = all_menu_dict[pid]
80 | parent_menu['children'].append(all_menu_dict[i])
81 | else:
82 | menu_data.append(all_menu_dict[i])
83 |
84 | return menu_data
85 |
86 |
87 | def get_menu_html(menu_data):
88 | """显示:菜单 + [子菜单] + 权限(url)"""
89 | option_str = """
90 |
96 | """
97 |
98 | url_str = """
99 | {permission_title}
100 | """
101 |
102 | """
103 | menu_data = [
104 | {'id': 1, 'title': '订单管理', 'parent_id': None, 'status': True, 'open': False,
105 | 'children': [{'title': '查看订单', 'url': '/order', 'menu_id': 1, 'status': True, 'open': False}]},
106 | {'id': 2, 'title': '库存管理', 'parent_id': None, 'status': True, 'open': True,
107 | 'children': [{'title': '查看库存清单', 'url': '/stock/detail', 'menu_id': 2, 'status': True, 'open': False},
108 | {'title': '入库', 'url': '/stock/in', 'menu_id': 2, 'status': True, 'open': True}]},
109 | {'id': 3, 'title': '生产管理', 'parent_id': None, 'status': True, 'open': False,
110 | 'children': [{'title': '查看生产订单', 'url': '/produce/detail', 'menu_id': 3, 'status': True, 'open': False},
111 | {'title': '排单', 'url': '/produce/new', 'menu_id': 3, 'status': True, 'open': False}]},
112 | {'id': 4, 'title': '生产调查', 'parent_id': None, 'status': True, 'open': False,
113 | 'children': [{'title': '产出管理', 'url': '/survey/produce', 'menu_id': 4, 'status': True, 'open': False},
114 | {'title': '工时管理', 'url': '/survey/labor', 'menu_id': 4, 'status': True, 'open': False}]}
115 | ]
116 | """
117 |
118 | menu_html = ''
119 | for item in menu_data:
120 | if not item['status']: # 如果用户权限不在某个菜单下,即item['status']=False, 不显示
121 | continue
122 | else:
123 | if item.get('url'): # 说明循环到了菜单最里层的url
124 | menu_html += url_str.format(permission_url=item['url'],
125 | active="rbac-active" if item['open'] else "",
126 | permission_title=item['title'])
127 | else:
128 | if item.get('children'):
129 | sub_menu = get_menu_html(item['children'])
130 | else:
131 | sub_menu = ""
132 |
133 | menu_html += option_str.format(menu_title=item['title'],
134 | sub_menu=sub_menu,
135 | display="" if item['open'] else "rbac-hide",
136 | status="open" if item['open'] else "close")
137 |
138 | return menu_html
139 |
140 |
141 | @register.simple_tag
142 | def rbac_menu(request):
143 | """
144 | 显示多级菜单:请求过来 -- 拿到session中的菜单,权限数据 -- 处理数据 -- 作显示
145 | 返回多级菜单:数据处理部分抽象出来由单独的函数处理;渲染部分也抽象出来由单独函数处理
146 | :param request:
147 | :return:
148 | """
149 | menu_data = get_structure_data(request)
150 | menu_html = get_menu_html(menu_data)
151 |
152 | return mark_safe(menu_html)
153 | # 因为标签无法使用safe过滤器,这里用mark_safe函数来实现
154 |
155 |
156 | @register.simple_tag
157 | def rbac_css():
158 | """
159 | rabc要用到的css文件路径,并读取返回;注意返回字符串用mark_safe,否则传到模板会转义
160 | :return:
161 | """
162 | css_path = os.path.join('rbac', 'style_script','rbac.css')
163 | css = open(css_path,'r',encoding='utf-8').read()
164 | return mark_safe(css)
165 |
166 |
167 | @register.simple_tag
168 | def rbac_js():
169 | """
170 | rabc要用到的js文件路径,并读取返回
171 | :return:
172 | """
173 | js_path = os.path.join('rbac', 'style_script', 'rbac.js')
174 | js = open(js_path, 'r', encoding='utf-8').read()
175 | return mark_safe(js)
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/rbac/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
5 | all_menu_dict = {
6 | 1: {'id': 1, 'caption': '用户管理', 'parent_id': None, "children": [], "status": False, "open": False},
7 | 2: {'id': 2, 'caption': '订单管理', 'parent_id': None, "children": [], "status": False, "open": False},
8 | 3: {'id': 3, 'caption': '其他', 'parent_id': None, "children": [], "status": False, "open": False},
9 | 4: {'id': 4, 'caption': '退货', 'parent_id': 2, "children": [], "status": True, "open": False},
10 | 5: {'id': 5, 'caption': '换货', 'parent_id': 2, "children": [], "status": False, "open": False}
11 | }
12 |
13 | permisson_url = [
14 | {'title': '权限1', 'url': '/test/', 'menu_id': 1},
15 | {'title': '权限2', 'url': '/test/', 'menu_id': 1},
16 | {'title': '权限3', 'url': '/login', 'menu_id': 4},
17 | {'title': '权限4', 'url': '/test/', 'menu_id': 5}
18 | ]
19 |
20 | request_rul = '/login'
21 | import re
22 |
23 | for url in permisson_url:
24 | # 添加两个状态:显示 和 展开
25 | url['status'] = True
26 | pattern = url['url']
27 | if re.match(pattern, request_rul):
28 | url['open'] = True
29 | else:
30 | url['open'] = False
31 |
32 | # 将url添加到菜单下
33 | all_menu_dict[url['menu_id']]["children"].append(url)
34 |
35 | # 显示菜单:url 的菜单及上层菜单 status: true
36 | pid = url['menu_id']
37 | while pid:
38 | all_menu_dict[pid]['status'] = True
39 | pid = all_menu_dict[pid]['parent_id']
40 |
41 | # 展开url上层菜单:url['open'] = True, 其菜单及其父菜单open = True
42 | if url['open']:
43 | ppid = url['menu_id']
44 | while ppid:
45 | all_menu_dict[ppid]['open'] = True
46 | ppid = all_menu_dict[ppid]['parent_id']
47 |
48 |
49 |
50 |
51 |
52 | print(all_menu_dict)
53 |
54 |
--------------------------------------------------------------------------------
/rbac/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from . import views
3 |
4 | urlpatterns = [
5 | url(r'^users/$', views.users),
6 | url(r'^users/new/$', views.users_new),
7 | url(r'^users/edit/(?P\d+)/$', views.users_edit),
8 | url(r'^users/delete/(?P\d+)/$', views.users_delete),
9 |
10 | url(r'^roles/$', views.roles),
11 | url(r'^roles/new/$', views.roles_new),
12 | url(r'^roles/edit/(?P\d+)/$', views.roles_edit),
13 | url(r'^roles/delete/(?P\d+)/$', views.roles_delete),
14 |
15 | url(r'^permissions/$', views.permissions),
16 | url(r'^permissions/new/$', views.permissions_new),
17 | url(r'^permissions/edit/(?P\d+)/$', views.permissions_edit),
18 | url(r'^permissions/delete/(?P\d+)/$', views.permissions_delete),
19 |
20 | url(r'^menus/$', views.menus),
21 | url(r'^menus/new/$', views.menus_new),
22 | url(r'^menus/edit/(?P\d+)/$', views.menus_edit),
23 | url(r'^menus/delete/(?P\d+)/$', views.menus_delete),
24 |
25 | url(r'^$', views.index)
26 | ]
27 |
--------------------------------------------------------------------------------
/rbac/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect, reverse
2 | from .models import UserInfo, Role, Permission, Menu
3 | from .forms import UserInfoModelForm, RoleModelForm, PermissionModelForm, MenuModelForm
4 |
5 |
6 | def index(request):
7 | return render(request, 'rbac/index.html')
8 |
9 |
10 | def users(request):
11 | """查询所有用户信息"""
12 | user_list = UserInfo.objects.all()
13 | return render(request, 'rbac/users.html', {'user_list': user_list})
14 |
15 |
16 | def users_new(request):
17 | if request.method =="GET":
18 | # 传入ModelForm对象
19 | model_form = UserInfoModelForm()
20 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增用户'})
21 | else:
22 | model_form = UserInfoModelForm(request.POST)
23 | if model_form.is_valid():
24 | model_form.save()
25 | return redirect(reverse(users))
26 | else:
27 | return render(request, 'rbac/common_edit.html',{'model_form': model_form, 'title': '新增用户'})
28 |
29 |
30 | def users_edit(request,id):
31 | user_obj = UserInfo.objects.filter(id=id).first()
32 | if request.method == 'GET':
33 | model_form = UserInfoModelForm(instance=user_obj)
34 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑用户'})
35 | else:
36 | model_form = UserInfoModelForm(request.POST, instance=user_obj)
37 | if model_form.is_valid():
38 | model_form.save()
39 | return redirect(reverse(users))
40 | else:
41 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑用户'})
42 |
43 |
44 | def users_delete(request, id):
45 | user_obj = UserInfo.objects.filter(id=id).first()
46 | user_obj.delete()
47 | return redirect(reverse(users))
48 |
49 |
50 | def roles(request):
51 | role_list = Role.objects.all()
52 | return render(request, 'rbac/roles.html', {'role_list': role_list})
53 |
54 |
55 | def roles_new(request):
56 | if request.method == "GET":
57 | # 传入ModelForm对象
58 | model_form = RoleModelForm()
59 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增角色'})
60 | else:
61 | model_form = RoleModelForm(request.POST)
62 | if model_form.is_valid():
63 | model_form.save()
64 | return redirect(reverse(roles))
65 | else:
66 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增角色'})
67 |
68 |
69 | def roles_edit(request, id):
70 | role_obj = Role.objects.filter(id=id).first()
71 | if request.method == 'GET':
72 | model_form = RoleModelForm(instance=role_obj)
73 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑角色'})
74 | else:
75 | model_form = RoleModelForm(request.POST, instance=role_obj)
76 | if model_form.is_valid():
77 | model_form.save()
78 | return redirect(reverse(roles))
79 | else:
80 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑角色'})
81 |
82 |
83 | def roles_delete(request, id):
84 | role_obj = Role.objects.filter(id=id).first()
85 | role_obj.delete()
86 | return redirect(reverse(roles))
87 |
88 |
89 | def permissions(request):
90 | permission_list = Permission.objects.all()
91 | return render(request, 'rbac/permissions.html', {'permission_list': permission_list})
92 |
93 |
94 | def permissions_new(request):
95 | if request.method == "GET":
96 | # 传入ModelForm对象
97 | model_form = PermissionModelForm()
98 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增权限'})
99 | else:
100 | model_form = PermissionModelForm(request.POST)
101 | if model_form.is_valid():
102 | model_form.save()
103 | return redirect(reverse(permissions))
104 | else:
105 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增权限'})
106 |
107 |
108 | def permissions_edit(request, id):
109 | permission_obj = Permission.objects.filter(id=id).first()
110 | if request.method == 'GET':
111 | model_form = PermissionModelForm(instance=permission_obj)
112 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑权限'})
113 | else:
114 | model_form = PermissionModelForm(request.POST, instance=permission_obj)
115 | if model_form.is_valid():
116 | model_form.save()
117 | return redirect(reverse(permissions))
118 | else:
119 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑权限'})
120 |
121 |
122 | def permissions_delete(request, id):
123 | permission_obj = Role.objects.filter(id=id).first()
124 | permission_obj.delete()
125 | return redirect(reverse(permissions))
126 |
127 |
128 | def menus(request):
129 | menu_list = Menu.objects.all()
130 | return render(request, 'rbac/menus.html', {'menu_list': menu_list})
131 |
132 |
133 | def menus_new(request):
134 | if request.method == "GET":
135 | # 传入ModelForm对象
136 | model_form = MenuModelForm()
137 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增菜单'})
138 | else:
139 | model_form = MenuModelForm(request.POST)
140 | if model_form.is_valid():
141 | model_form.save()
142 | return redirect(reverse(menus))
143 | else:
144 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '新增菜单'})
145 |
146 |
147 | def menus_edit(request, id):
148 | menu_obj = Menu.objects.filter(id=id).first()
149 | if request.method == 'GET':
150 | model_form = MenuModelForm(instance=menu_obj)
151 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑菜单'})
152 | else:
153 | model_form = MenuModelForm(request.POST, instance=menu_obj)
154 | if model_form.is_valid():
155 | model_form.save()
156 | return redirect(reverse(menus))
157 | else:
158 | return render(request, 'rbac/common_edit.html', {'model_form': model_form, 'title': '编辑菜单'})
159 |
160 |
161 | def menus_delete(request, id):
162 | menu_obj = Role.objects.filter(id=id).first()
163 | menu_obj.delete()
164 | return redirect(reverse(menus))
165 |
166 |
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 | {% load custom_tag %}
2 | {% load static %}
3 |
4 |
5 |
6 |
7 | Title
8 | {# 通过调用自定义标签中的函数,导入rbac中的css和js #}
9 |
12 |
13 |
18 |
19 |
20 |
21 |
22 | {% rbac_menu request %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
19 |
20 |
21 |
--------------------------------------------------------------------------------