数据库表结构
models.py
from django.db import models
class Permission(models.Model):
""" 权限表 """
code = models.CharField(verbose_name="路由名称", max_length=32)
name = models.CharField(verbose_name="名称", max_length=32)
class Role(models.Model):
""" 角色表 """
name = models.CharField(verbose_name="名称", max_length=32)
permissions = models.ManyToManyField(verbose_name="权限", to="Permission")
class User(models.Model):
""" 用户表 """
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=32)
is_super = models.BooleanField(verbose_name="是否管理员", default=False)
roles = models.ManyToManyField(verbose_name="权限", to="Role")
class Computer(models.Model):
""" 电脑 """
title = models.CharField(verbose_name="名称", max_length=32)
price = models.IntegerField(verbose_name="价格")
class Order(models.Model):
""" 订单 """
title = models.CharField(verbose_name="订单", max_length=32)
price = models.IntegerField(verbose_name="价格")
使用命令行创建超级用户
management/commands/superuser.py
from django.core.management.base import BaseCommand
from www import models
class Command(BaseCommand):
def handle(self, *args, **options):
username = input("请输入用户名:")
password = input("请输入密码:")
models.User.objects.create(username=username, password=password, is_super=True)
使用离线脚本创建角色和用户
scripts/创建普通用户及权限.py
import django
import os
import sys
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rbac.settings')
django.setup()
from www import models
#
# models.Permission.objects.bulk_create([
# models.Permission(code="computer", name="电脑管理"),
# models.Permission(code="computer_add", name="电脑添加"),
# models.Permission(code="computer_edit", name="电脑编辑"),
# models.Permission(code="computer_del", name="电脑删除"),
# ])
#
# role = models.Role.objects.create(name="运营实习生")
# role.permissions.set([1, 2])
#
# role = models.Role.objects.create(name="正式员工")
# role.permissions.set([1, 2, 3, 4])
#
# user = models.User.objects.create(username="cqn", password="123", is_super=False)
# user.roles.set([1])
#
# user = models.User.objects.create(username="zkf", password="123", is_super=False)
# user.roles.set([1, 2])
urls.py
"""
URL configuration for rbac project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path
from www import views
urlpatterns = [
path('login/', views.login, name="login"),
path('home/', views.home, name="home"),
path('computer/', views.computer, name="computer"),
path('computer/add/', views.computer_add, name="computer_add"),
path('computer/edit/<int:id>/', views.computer_edit, name="computer_edit"),
path('computer/del/<int:id>/', views.computer_del, name="computer_del"),
path('order/', views.order, name="order"),
path('order/add/', views.order_add, name="order_add"),
path('order/edit/<int:id>/', views.order_edit, name="order_edit"),
path('order/del/<int:id>/', views.order_del, name="order_del"),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.forms import ModelForm
from django.forms.models import model_to_dict
from www import models
class LoginModelForm(ModelForm):
class Meta:
model = models.User
fields = ["username", "password"]
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
form = LoginModelForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
user_object = models.User.objects.filter(**form.cleaned_data).first()
if not user_object:
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# request.session["user_session_key"] = {
# "id": user_object.id,
# "username": user_object.username,
# "is_super": user_object.is_super
# }
request.session["user_session_key"] = model_to_dict(user_object, fields=["id", "username", "is_super"])
return redirect("home")
def home(request):
return HttpResponse("HOME")
def computer(request):
return render(request, 'computer.html')
def computer_add(request):
return HttpResponse("OK")
def computer_edit(request, id):
return HttpResponse("OK")
def computer_del(request, id):
return HttpResponse("OK")
def order(request):
return HttpResponse("OK")
def order_add(request):
return HttpResponse("OK")
def order_edit(request, id):
return HttpResponse("OK")
def order_del(request, id):
return HttpResponse("OK")
中间件
utils/md.py
from django.contrib.auth.middleware import MiddlewareMixin
from django.urls import reverse
from django.shortcuts import redirect, HttpResponse
from www import models
class AuthMiddleware(MiddlewareMixin):
def process_request(self, request):
if request.path_info in [reverse("login")]:
return
user_dict = request.session.get("user_session_key")
if not user_dict:
return redirect("login")
request.user_dict = user_dict
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, callback, *args, **kwargs):
if request.path_info in [reverse("login")]:
return
if request.user_dict["is_super"]:
return
# 用户访问的rl
url_name = request.resolver_match.url_name
print("PermissionMiddleware中间件: ", url_name)
# 用户对象
user_object = models.User.objects.filter(id=request.user_dict['id']).first()
# 用户所有的角色,角色对应的权限
user_per_list = user_object.roles.all().values("permissions__code", "permissions__name")
permission_dict = {item["permissions__code"]: item["permissions__name"] for item in user_per_list}
print("PermissionMiddleware中间件: ", permission_dict)
request.permission_dict = permission_dict
if url_name in permission_dict:
return
return HttpResponse("无权访问")
前端页面
templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>用户登录</h2>
<form method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">登录</button>
</form>
</body>
</html>
templates/computer.html
{% load permission %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if request|has_permission:"computer_add" %}
<a href="{% url "computer_add" %}">新增</a>
{% endif %}
{% if request|has_permission:"computer_edit" %}
<a href="{% url "computer_edit" id=1 %}">编辑</a>
{% endif %}
{% if request|has_permission:"computer_del" %}
<a href="{% url "computer_del" id=1 %}">删除</a>
{% endif %}
</body>
</html>
templatetags/permission.py
from django.template import Library
register = Library()
@register.filter
def has_permission(request, route_name):
is_super = request.user_dict['is_super']
if is_super:
return True
if route_name in request.permission_dict:
return True
return False
路由管理
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.forms import ModelForm
from django.forms.models import model_to_dict
from www import models
class LoginModelForm(ModelForm):
class Meta:
model = models.User
fields = ["username", "password"]
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
form = LoginModelForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
user_object = models.User.objects.filter(**form.cleaned_data).first()
if not user_object:
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# request.session["user_session_key"] = {
# "id": user_object.id,
# "username": user_object.username,
# "is_super": user_object.is_super
# }
request.session["user_session_key"] = model_to_dict(user_object, fields=["id", "username", "is_super"])
return redirect("home")
def home(request):
return HttpResponse("HOME")
from django.conf import settings
from importlib import import_module
from django.urls.resolvers import URLResolver, URLPattern
def get_all_url_permission():
# 1、找到根路由 settings.ROOT_URLCONF, 'rbac.urls'
root = import_module(settings.ROOT_URLCONF)
# 2、找到跟路由列表
# print(root.urlpatterns)
#
# for obj in root.urlpatterns:
# if type(obj) == URLPattern:
# print("URLPattern: ", obj)
# continue
# if type(obj) == URLResolver:
# print("URLResolver: ", obj.url_patterns)
# for item in obj.url_patterns:
# print("\t", item)
# 4、多层级的路由处理
resolver_list = [root]
for resolver in resolver_list:
# patterns = resolver.urlpatterns 或者 resolver.url_patterns
patterns = getattr(resolver, "urlpatterns", None) or getattr(resolver, "url_patterns", None)
for item in patterns:
if type(item) == URLPattern:
print("URLPattern: ", item.name, item)
continue
if type(item) == URLResolver:
resolver_list.append(item)
def permission(request):
if request.method == "POST":
# 1、读取项目中所有权限(路由)
data = get_all_url_permission()
pass
queryset = models.Permission.objects.all()
return render(request, 'permission.html', {"queryset": queryset})
def computer(request):
return render(request, 'computer.html')
def computer_add(request):
return HttpResponse("OK")
def computer_edit(request, id):
return HttpResponse("OK")
def computer_del(request, id):
return HttpResponse("OK")
def order(request):
return HttpResponse("OK")
def order_add(request):
return HttpResponse("OK")
def order_edit(request, id):
return HttpResponse("OK")
def order_del(request, id):
return HttpResponse("OK")
rbac/urls.py
"""
URL configuration for rbac project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path, include
from www import views
urlpatterns = [
path('login/', views.login, name="login"),
path('home/', views.home, name="home"),
path('permission/', views.permission, name="permission"),
path('computer/', views.computer, name="computer"),
path('computer/add/', views.computer_add, name="computer_add"),
path('computer/edit/<int:id>/', views.computer_edit, name="computer_edit"),
path('computer/del/<int:id>/', views.computer_del, name="computer_del"),
path('order/', views.order, name="order"),
path('order/add/', views.order_add, name="order_add"),
path('order/edit/<int:id>/', views.order_edit, name="order_edit"),
path('order/del/<int:id>/', views.order_del, name="order_del"),
path('app01/', include("app01.urls")),
path('app02/', include("app02.urls")),
]
app01/urls.py
from django.urls import path
from app01 import views
urlpatterns = [
path('test1/', views.test1, name="test1")
]
添加路由的中文信息
utils/ext_urls.py
from functools import partial
from importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from django.urls.resolvers import (
LocalePrefixPattern,
RegexPattern,
RoutePattern,
URLPattern,
URLResolver,
)
class RbacPattern(URLPattern):
def __init__(self, pattern, callback, default_args=None, name=None, text=None):
super().__init__(pattern, callback, default_args, name)
self.text = text
def _path(route, view, kwargs=None, name=None, text=None, Pattern=None):
from django.views import View
if kwargs is not None and not isinstance(kwargs, dict):
raise TypeError(
f"kwargs argument must be a dict, but got {kwargs.__class__.__name__}."
)
if isinstance(view, (list, tuple)):
# For include(...) processing.
pattern = Pattern(route, is_endpoint=False)
urlconf_module, app_name, namespace = view
return URLResolver(
pattern,
urlconf_module,
kwargs,
app_name=app_name,
namespace=namespace,
)
elif callable(view):
pattern = Pattern(route, name=name, is_endpoint=True)
return RbacPattern(pattern, view, kwargs, name, text)
elif isinstance(view, View):
view_cls_name = view.__class__.__name__
raise TypeError(
f"view must be a callable, pass {view_cls_name}.as_view(), not "
f"{view_cls_name}()."
)
else:
raise TypeError(
"view must be a callable or a list/tuple in the case of include()."
)
rbac_path = partial(_path, Pattern=RoutePattern)
rbac_re_path = partial(_path, Pattern=RegexPattern)
urls.py
"""
URL configuration for rbac project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path, include
from www import views
from www.utils.ext_url import rbac_path
urlpatterns = [
path('login/', views.login, name="login"),
rbac_path('home/', views.home, name="home", text="家目录"),
# rbac_path('demo/', views.home, name="demo", text="测试"),
rbac_path('permission/', views.permission, name="permission", text="权限管理"),
rbac_path('computer/', views.computer, name="computer", text="电脑管理"),
rbac_path('computer/add/', views.computer_add, name="computer_add", text="电脑增加"),
rbac_path('computer/edit/<int:id>/', views.computer_edit, name="computer_edit", text="电脑编辑"),
rbac_path('computer/del/<int:id>/', views.computer_del, name="computer_del", text="电脑删除"),
rbac_path('order/', views.order, name="order", text="订单管理"),
rbac_path('order/add/', views.order_add, name="order_add", text="订单增加"),
rbac_path('order/edit/<int:id>/', views.order_edit, name="order_edit", text="订单编辑"),
rbac_path('order/del/<int:id>/', views.order_del, name="order_del", text="订单删除"),
rbac_path('app01/', include("app01.urls")),
rbac_path('app02/', include("app02.urls", namespace='app02')),
]
app02/urls.py
from app02 import views
from www.utils.ext_url import rbac_path
urlpatterns = [
rbac_path('test2/', views.test2, name="test2", text="test2"),
rbac_path('test3/', views.test3, name="test3", text="test3")
]
app_name = "app02"
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.forms import ModelForm
from django.forms.models import model_to_dict
from www import models
class LoginModelForm(ModelForm):
class Meta:
model = models.User
fields = ["username", "password"]
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
form = LoginModelForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
user_object = models.User.objects.filter(**form.cleaned_data).first()
if not user_object:
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# request.session["user_session_key"] = {
# "id": user_object.id,
# "username": user_object.username,
# "is_super": user_object.is_super
# }
request.session["user_session_key"] = model_to_dict(user_object, fields=["id", "username", "is_super"])
return redirect("home")
def home(request):
return HttpResponse("HOME")
from django.conf import settings
from importlib import import_module
from django.urls.resolvers import URLResolver, URLPattern
from www.utils.ext_url import RbacPattern
def get_all_url_permission():
# 1、找到根路由 settings.ROOT_URLCONF, 'rbac.urls'
root = import_module(settings.ROOT_URLCONF)
# 2、找到跟路由列表
# print(root.urlpatterns)
#
# for obj in root.urlpatterns:
# if type(obj) == URLPattern:
# print("URLPattern: ", obj)
# continue
# if type(obj) == URLResolver:
# print("URLResolver: ", obj.url_patterns)
# for item in obj.url_patterns:
# print("\t", item)
# 4、多层级的路由处理
resolver_list = [(root, None)]
local_dict = {}
for resolver, pre_namespace in resolver_list:
# patterns = resolver.urlpatterns 或者 resolver.url_patterns
patterns = getattr(resolver, "urlpatterns", None) or getattr(resolver, "url_patterns", None)
for item in patterns:
# if type(item) == URLPattern:
# print("URLPattern: ", item.name, item)
# continue
if type(item) == RbacPattern:
# print("RbacPattern: ", item.name, item)
code = f"{pre_namespace}:{item.name}" if pre_namespace else item.name
local_dict[code] = item.text
continue
if type(item) == URLResolver:
namespace_list = [ele for ele in [pre_namespace, item.namespace] if ele]
total_namespace = ":".join(namespace_list) if namespace_list else None
resolver_list.append((item, total_namespace))
return local_dict
def permission(request):
if request.method == "POST":
# 1、读取项目中所有权限(路由)
local_route_dict = get_all_url_permission()
local_route_set = set(local_route_dict)
# 2、读物数据库已有权限(路由)
db_pers = models.Permission.objects.all()
db_pers_dict = {item.code: item.name for item in db_pers}
db_pers_set = set(db_pers_dict)
# 3、对比:增加、删除、更新
# 增加
models.Permission.objects.bulk_create(
[models.Permission(code=code, name=local_route_dict[code]) for code in local_route_set - db_pers_set]
)
# 删除
models.Permission.objects.filter(code__in=db_pers_set - local_route_set).delete()
# 更新
for code in db_pers_set & local_route_set:
if db_pers_dict[code] == local_route_dict[code]:
continue
models.Permission.objects.filter(code=code).update(name=local_route_dict[code])
queryset = models.Permission.objects.all()
return render(request, 'permission.html', {"queryset": queryset})
def computer(request):
return render(request, 'computer.html')
def computer_add(request):
return HttpResponse("OK")
def computer_edit(request, id):
return HttpResponse("OK")
def computer_del(request, id):
return HttpResponse("OK")
def order(request):
return HttpResponse("OK")
def order_add(request):
return HttpResponse("OK")
def order_edit(request, id):
return HttpResponse("OK")
def order_del(request, id):
return HttpResponse("OK")
用户管理和角色管理
urls.py
from django.urls import path, include
from www import views
from www.utils.ext_url import rbac_path
urlpatterns = [
path('login/', views.login, name="login"),
rbac_path('home/', views.home, name="home", text="家目录"),
# rbac_path('demo/', views.home, name="demo", text="测试"),
rbac_path('permission/', views.permission, name="permission", text="权限管理"),
rbac_path('computer/', views.computer, name="computer", text="电脑管理"),
rbac_path('computer/add/', views.computer_add, name="computer_add", text="电脑增加"),
rbac_path('computer/edit/<int:id>/', views.computer_edit, name="computer_edit", text="电脑编辑"),
rbac_path('computer/del/<int:id>/', views.computer_del, name="computer_del", text="电脑删除"),
rbac_path('role/', views.role, name="role", text="角色管理"),
rbac_path('role/add/', views.role_add, name="role_add", text="角色增加"),
rbac_path('role/edit/<int:id>/', views.role_edit, name="role_edit", text="角色编辑"),
rbac_path('role/del/<int:id>/', views.role_del, name="role_del", text="角色删除"),
rbac_path('user/', views.user, name="user", text="用户管理"),
rbac_path('user/add/', views.user_add, name="user_add", text="用户增加"),
rbac_path('user/edit/<int:id>/', views.user_edit, name="user_edit", text="用户编辑"),
rbac_path('user/del/<int:id>/', views.user_del, name="user_del", text="用户删除"),
rbac_path('order/', views.order, name="order", text="订单管理"),
rbac_path('order/add/', views.order_add, name="order_add", text="订单增加"),
rbac_path('order/edit/<int:id>/', views.order_edit, name="order_edit", text="订单编辑"),
rbac_path('order/del/<int:id>/', views.order_del, name="order_del", text="订单删除"),
rbac_path('app01/', include("app01.urls")),
rbac_path('app02/', include("app02.urls", namespace='app02')),
]
view.py
from django.shortcuts import render, HttpResponse, redirect
from django.forms import ModelForm
from django.forms.models import model_to_dict
from www import models
class LoginModelForm(ModelForm):
class Meta:
model = models.User
fields = ["username", "password"]
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
form = LoginModelForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
user_object = models.User.objects.filter(**form.cleaned_data).first()
if not user_object:
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# request.session["user_session_key"] = {
# "id": user_object.id,
# "username": user_object.username,
# "is_super": user_object.is_super
# }
request.session["user_session_key"] = model_to_dict(user_object, fields=["id", "username", "is_super"])
return redirect("home")
def home(request):
return HttpResponse("HOME")
from django.conf import settings
from importlib import import_module
from django.urls.resolvers import URLResolver, URLPattern
from www.utils.ext_url import RbacPattern
def get_all_url_permission():
# 1、找到根路由 settings.ROOT_URLCONF, 'rbac.urls'
root = import_module(settings.ROOT_URLCONF)
# 2、找到跟路由列表
# print(root.urlpatterns)
#
# for obj in root.urlpatterns:
# if type(obj) == URLPattern:
# print("URLPattern: ", obj)
# continue
# if type(obj) == URLResolver:
# print("URLResolver: ", obj.url_patterns)
# for item in obj.url_patterns:
# print("\t", item)
# 4、多层级的路由处理
resolver_list = [(root, None)]
local_dict = {}
for resolver, pre_namespace in resolver_list:
# patterns = resolver.urlpatterns 或者 resolver.url_patterns
patterns = getattr(resolver, "urlpatterns", None) or getattr(resolver, "url_patterns", None)
for item in patterns:
# if type(item) == URLPattern:
# print("URLPattern: ", item.name, item)
# continue
if type(item) == RbacPattern:
# print("RbacPattern: ", item.name, item)
code = f"{pre_namespace}:{item.name}" if pre_namespace else item.name
local_dict[code] = item.text
continue
if type(item) == URLResolver:
namespace_list = [ele for ele in [pre_namespace, item.namespace] if ele]
total_namespace = ":".join(namespace_list) if namespace_list else None
resolver_list.append((item, total_namespace))
return local_dict
def permission(request):
if request.method == "POST":
# 1、读取项目中所有权限(路由)
local_route_dict = get_all_url_permission()
local_route_set = set(local_route_dict)
# 2、读物数据库已有权限(路由)
db_pers = models.Permission.objects.all()
db_pers_dict = {item.code: item.name for item in db_pers}
db_pers_set = set(db_pers_dict)
# 3、对比:增加、删除、更新
# 增加
models.Permission.objects.bulk_create(
[models.Permission(code=code, name=local_route_dict[code]) for code in local_route_set - db_pers_set]
)
# 删除
models.Permission.objects.filter(code__in=db_pers_set - local_route_set).delete()
# 更新
for code in db_pers_set & local_route_set:
if db_pers_dict[code] == local_route_dict[code]:
continue
models.Permission.objects.filter(code=code).update(name=local_route_dict[code])
queryset = models.Permission.objects.all()
return render(request, 'permission.html', {"queryset": queryset})
def computer(request):
return render(request, 'computer.html')
def computer_add(request):
return HttpResponse("OK")
def computer_edit(request, id):
return HttpResponse("OK")
def computer_del(request, id):
return HttpResponse("OK")
class RoleModelForm(ModelForm):
class Meta:
model = models.Role
fields = "__all__"
def role(request):
queryset = models.Role.objects.all()
return render(request, 'role.html', {"queryset": queryset})
def role_add(request):
if request.method == "GET":
form = RoleModelForm()
return render(request, 'form.html', {"form": form})
form = RoleModelForm(data=request.POST)
if not form.is_valid():
return render(request, 'form.html', {"form": form})
form.save()
return redirect(to="role")
def role_edit(request, id):
instance = models.Role.objects.filter(id=id).first()
if request.method == "GET":
form = RoleModelForm(instance=instance)
return render(request, 'form.html', {"form": form})
form = RoleModelForm(data=request.POST, instance=instance)
if not form.is_valid():
return render(request, 'form.html', {"form": form})
form.save()
return redirect(to="role")
def role_del(request, id):
models.Role.objects.filter(id=id).first().delete()
return redirect(to="role")
class UserModelForm(ModelForm):
class Meta:
model = models.User
fields = "__all__"
def user(request):
if request.method == "GET":
queryset = models.User.objects.all()
return render(request, "user.html", {"queryset": queryset})
return HttpResponse("OK")
def user_add(request):
if request.method == "GET":
form = UserModelForm()
return render(request, "form.html", {"form": form})
form = UserModelForm(data=request.POST)
if not form.is_valid():
return render(request, "form.html", {"form": form})
form.save()
return redirect(to="user")
def user_edit(request, id):
instance = models.User.objects.filter(id=id).first()
if request.method == "GET":
form = UserModelForm(instance=instance)
return render(request, "form.html", {"form": form})
form = UserModelForm(instance=instance, data=request.POST)
if not form.is_valid():
return render(request, "user.html", {"form": form})
form.save()
return redirect(to="user")
def user_del(request, id):
models.User.objects.filter(id=id).delete()
return redirect(to="user")
def order(request):
return HttpResponse("OK")
def order_add(request):
return HttpResponse("OK")
def order_edit(request, id):
return HttpResponse("OK")
def order_del(request, id):
return HttpResponse("OK")
form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">提交</button>
</form>
</body>
</html>
role.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="{% url 'role_add' %}">新增</a>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>
<a href="{% url 'role_edit' id=row.id %}">编辑</a>
<a href="{% url 'role_del' id=row.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="{% url 'user_add' %}">新增</a>
<table border="1">
<thead>
<tr>
<th>用户名</th>
<th>密码</th>
<th>超级管理员</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{{ row.username }}</td>
<td>{{ row.password }}</td>
<td>{{ row.is_super }}</td>
<td>
<a href="{% url 'user_edit' id=row.id %}">编辑</a>
<a href="{% url 'user_del' id=row.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
添加菜单管理
models.py
from django.db import models
class Permission(models.Model):
""" 权限表 """
code = models.CharField(verbose_name="路由名称", max_length=32)
name = models.CharField(verbose_name="名称", max_length=32)
def __str__(self):
return self.name
class Role(models.Model):
""" 角色表 """
name = models.CharField(verbose_name="名称", max_length=32)
permissions = models.ManyToManyField(verbose_name="权限", to="Permission")
def __str__(self):
return self.name
class User(models.Model):
""" 用户表 """
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=32)
is_super = models.BooleanField(verbose_name="是否管理员", default=False)
roles = models.ManyToManyField(verbose_name="权限", to="Role", blank=True)
menus = models.ManyToManyField(verbose_name="菜单", to="Menu", blank=True)
class Computer(models.Model):
""" 电脑 """
title = models.CharField(verbose_name="名称", max_length=32)
price = models.IntegerField(verbose_name="价格")
class Order(models.Model):
""" 订单 """
title = models.CharField(verbose_name="订单", max_length=32)
price = models.IntegerField(verbose_name="价格")
class Menu(models.Model):
""" 菜单 """
title = models.CharField(verbose_name="名称", max_length=32)
permissions = models.ManyToManyField(verbose_name="权限", to="Permission")
def __str__(self):
return self.title
urls.py
"""
URL configuration for rbac project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path, include
from www import views
from www.utils.ext_url import rbac_path
urlpatterns = [
path('login/', views.login, name="login"),
rbac_path('home/', views.home, name="home", text="家目录"),
# rbac_path('demo/', views.home, name="demo", text="测试"),
rbac_path('permission/', views.permission, name="permission", text="权限管理"),
rbac_path('computer/', views.computer, name="computer", text="电脑管理"),
rbac_path('computer/add/', views.computer_add, name="computer_add", text="电脑增加"),
rbac_path('computer/edit/<int:id>/', views.computer_edit, name="computer_edit", text="电脑编辑"),
rbac_path('computer/del/<int:id>/', views.computer_del, name="computer_del", text="电脑删除"),
rbac_path('role/', views.role, name="role", text="角色管理"),
rbac_path('role/add/', views.role_add, name="role_add", text="角色增加"),
rbac_path('role/edit/<int:id>/', views.role_edit, name="role_edit", text="角色编辑"),
rbac_path('role/del/<int:id>/', views.role_del, name="role_del", text="角色删除"),
rbac_path('user/', views.user, name="user", text="用户管理"),
rbac_path('user/add/', views.user_add, name="user_add", text="用户增加"),
rbac_path('user/edit/<int:id>/', views.user_edit, name="user_edit", text="用户编辑"),
rbac_path('user/del/<int:id>/', views.user_del, name="user_del", text="用户删除"),
rbac_path('order/', views.order, name="order", text="订单管理"),
rbac_path('order/add/', views.order_add, name="order_add", text="订单增加"),
rbac_path('order/edit/<int:id>/', views.order_edit, name="order_edit", text="订单编辑"),
rbac_path('order/del/<int:id>/', views.order_del, name="order_del", text="订单删除"),
rbac_path('menu/', views.menu, name="menu", text="菜单管理"),
rbac_path('menu/add/', views.menu_add, name="menu_add", text="菜单增加"),
rbac_path('menu/edit/<int:id>/', views.menu_edit, name="menu_edit", text="菜单编辑"),
rbac_path('menu/del/<int:id>/', views.menu_del, name="menu_del", text="菜单删除"),
# rbac_path('app01/', include("app01.urls")),
# rbac_path('app02/', include("app02.urls", namespace='app02')),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.forms import ModelForm
from django.forms.models import model_to_dict
from www import models
class LoginModelForm(ModelForm):
class Meta:
model = models.User
fields = ["username", "password"]
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
form = LoginModelForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
user_object = models.User.objects.filter(**form.cleaned_data).first()
if not user_object:
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# request.session["user_session_key"] = {
# "id": user_object.id,
# "username": user_object.username,
# "is_super": user_object.is_super
# }
request.session["user_session_key"] = model_to_dict(user_object, fields=["id", "username", "is_super"])
return redirect("home")
def home(request):
return render(request, "home.html")
from django.conf import settings
from importlib import import_module
from django.urls.resolvers import URLResolver, URLPattern
from www.utils.ext_url import RbacPattern
def get_all_url_permission():
# 1、找到根路由 settings.ROOT_URLCONF, 'rbac.urls'
root = import_module(settings.ROOT_URLCONF)
# 2、找到跟路由列表
# print(root.urlpatterns)
#
# for obj in root.urlpatterns:
# if type(obj) == URLPattern:
# print("URLPattern: ", obj)
# continue
# if type(obj) == URLResolver:
# print("URLResolver: ", obj.url_patterns)
# for item in obj.url_patterns:
# print("\t", item)
# 4、多层级的路由处理
resolver_list = [(root, None)]
local_dict = {}
for resolver, pre_namespace in resolver_list:
# patterns = resolver.urlpatterns 或者 resolver.url_patterns
patterns = getattr(resolver, "urlpatterns", None) or getattr(resolver, "url_patterns", None)
for item in patterns:
# if type(item) == URLPattern:
# print("URLPattern: ", item.name, item)
# continue
if type(item) == RbacPattern:
# print("RbacPattern: ", item.name, item)
code = f"{pre_namespace}:{item.name}" if pre_namespace else item.name
local_dict[code] = item.text
continue
if type(item) == URLResolver:
namespace_list = [ele for ele in [pre_namespace, item.namespace] if ele]
total_namespace = ":".join(namespace_list) if namespace_list else None
resolver_list.append((item, total_namespace))
return local_dict
def permission(request):
if request.method == "POST":
# 1、读取项目中所有权限(路由)
local_route_dict = get_all_url_permission()
local_route_set = set(local_route_dict)
# 2、读物数据库已有权限(路由)
db_pers = models.Permission.objects.all()
db_pers_dict = {item.code: item.name for item in db_pers}
db_pers_set = set(db_pers_dict)
# 3、对比:增加、删除、更新
# 增加
models.Permission.objects.bulk_create(
[models.Permission(code=code, name=local_route_dict[code]) for code in local_route_set - db_pers_set]
)
# 删除
models.Permission.objects.filter(code__in=db_pers_set - local_route_set).delete()
# 更新
for code in db_pers_set & local_route_set:
if db_pers_dict[code] == local_route_dict[code]:
continue
models.Permission.objects.filter(code=code).update(name=local_route_dict[code])
queryset = models.Permission.objects.all()
return render(request, 'permission.html', {"queryset": queryset})
def computer(request):
return render(request, 'computer.html')
def computer_add(request):
return HttpResponse("OK")
def computer_edit(request, id):
return HttpResponse("OK")
def computer_del(request, id):
return HttpResponse("OK")
class RoleModelForm(ModelForm):
class Meta:
model = models.Role
fields = "__all__"
def role(request):
queryset = models.Role.objects.all()
return render(request, 'role.html', {"queryset": queryset})
def role_add(request):
if request.method == "GET":
form = RoleModelForm()
return render(request, 'form.html', {"form": form})
form = RoleModelForm(data=request.POST)
if not form.is_valid():
return render(request, 'form.html', {"form": form})
form.save()
return redirect(to="role")
def role_edit(request, id):
instance = models.Role.objects.filter(id=id).first()
if request.method == "GET":
form = RoleModelForm(instance=instance)
return render(request, 'form.html', {"form": form})
form = RoleModelForm(data=request.POST, instance=instance)
if not form.is_valid():
return render(request, 'form.html', {"form": form})
form.save()
return redirect(to="role")
def role_del(request, id):
models.Role.objects.filter(id=id).first().delete()
return redirect(to="role")
class UserModelForm(ModelForm):
class Meta:
model = models.User
fields = "__all__"
def user(request):
if request.method == "GET":
queryset = models.User.objects.all()
return render(request, "user.html", {"queryset": queryset})
return HttpResponse("OK")
def user_add(request):
if request.method == "GET":
form = UserModelForm()
return render(request, "form.html", {"form": form})
form = UserModelForm(data=request.POST)
if not form.is_valid():
return render(request, "form.html", {"form": form})
form.save()
return redirect(to="user")
def user_edit(request, id):
instance = models.User.objects.filter(id=id).first()
if request.method == "GET":
form = UserModelForm(instance=instance)
return render(request, "form.html", {"form": form})
form = UserModelForm(instance=instance, data=request.POST)
if not form.is_valid():
return render(request, "user.html", {"form": form})
form.save()
return redirect(to="user")
def user_del(request, id):
models.User.objects.filter(id=id).delete()
return redirect(to="user")
def order(request):
return HttpResponse("OK")
def order_add(request):
return HttpResponse("OK")
def order_edit(request, id):
return HttpResponse("OK")
def order_del(request, id):
return HttpResponse("OK")
class MenuModelForm(ModelForm):
class Meta:
model = models.Menu
fields = "__all__"
def menu(request):
if request.method == "GET":
queryset = models.Menu.objects.all()
return render(request, "menu.html", {"queryset": queryset})
return HttpResponse("OK")
def menu_add(request):
if request.method == "GET":
form = MenuModelForm()
return render(request, "form.html", {"form": form})
form = MenuModelForm(data=request.POST)
if not form.is_valid():
return render(request, "form.html", {"form": form})
form.save()
return redirect(to="menu")
def menu_edit(request, id):
instance = models.Menu.objects.filter(id=id).first()
if request.method == "GET":
form = MenuModelForm(instance=instance)
return render(request, "form.html", {"form": form})
form = MenuModelForm(instance=instance, data=request.POST)
if not form.is_valid():
return render(request, "menu.html", {"form": form})
form.save()
return redirect(to="menu")
def menu_del(request, id):
models.Menu.objects.filter(id=id).delete()
return redirect(to="menu")
layout.html
{% load menu %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
margin: 0;
}
.pg-header {
height: 48px;
background-color: aquamarine;
}
.pg-body > .menu {
position: absolute;
left: 0;
top: 48px;
bottom: 0;
width: 220px;
background-color: #ddd;
}
.pg-body > .body {
position: absolute;
left: 220px;
top: 48px;
bottom: 0;
right: 0;
}
</style>
</head>
<body>
<div class="pg-header"></div>
<div class="pg-body">
<div class="menu">
{% menu request %}
</div>
<div class="body">
{% block body %}
{% endblock %}
</div>
</div>
</body>
</html>
computer.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
{% if request|has_permission:"computer_add" %}
<a href="{% url "computer_add" %}">新增</a>
{% endif %}
{% if request|has_permission:"computer_edit" %}
<a href="{% url "computer_edit" id=1 %}">编辑</a>
{% endif %}
{% if request|has_permission:"computer_del" %}
<a href="{% url "computer_del" id=1 %}">删除</a>
{% endif %}
{% endblock %}'
form.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<form method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">提交</button>
</form>
{% endblock %}
home.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<h1>欢迎登录</h1>
{% endblock %}
menu.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<a href="{% url 'menu_add' %}">新增</a>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>菜单名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for item in queryset %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.title }}</td>
<td>
<a href="{% url 'menu_edit' id=item.id %}">编辑</a>
<a href="{% url 'menu_del' id=item.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
permission.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<form method="post">
{% csrf_token %}
<input type="submit" value="同步">
</form>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>CODE</th>
</tr>
</thead>
<tbody>
{% for item in queryset %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.code }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
role.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<a href="{% url 'role_add' %}">新增</a>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>
<a href="{% url 'role_edit' id=row.id %}">编辑</a>
<a href="{% url 'role_del' id=row.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
user.html
{% extends "layout.html" %}
{% load permission %}
{% block body %}
<a href="{% url 'user_add' %}">新增</a>
<table border="1">
<thead>
<tr>
<th>用户名</th>
<th>密码</th>
<th>超级管理员</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{{ row.username }}</td>
<td>{{ row.password }}</td>
<td>{{ row.is_super }}</td>
<td>
<a href="{% url 'user_edit' id=row.id %}">编辑</a>
<a href="{% url 'user_del' id=row.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
templatetags/menu.py
from django.template import Library
register = Library()
@register.inclusion_tag("include/menu.html")
def menu(request):
menu_dict = {}
# 1、获取当前用户的所有菜单
# print(request.menu_list)
# 2、获取当前用户的所有权限
# print(request.permission_dict)
# 3、将菜单中当前用户无权限的,进行剔除
for item in request.menu_list:
id, title, name, code = item['id'], item['title'], item['permissions__name'], item['permissions__code']
menu_dict.setdefault(id, {"title": title, "children": []})
if request.user_dict['is_super']:
menu_dict[id]['children'].append({"name": name, "code": code})
continue
if code not in request.permission_dict:
continue
menu_dict[id]['children'].append({"name": name, "code": code})
print(menu_dict)
return {"menu_dict": menu_dict}
templates/include/menu.html
{% for item in menu_dict.values %}
<div>{{ item.title }}</div>
{% if item.children %}
{% for child in item.children %}
<a style="display: block" href="{% url child.code %}">{{ child.name }}</a>
{% endfor %}
{% endif %}
{% endfor %}
utils/md.py
from django.contrib.auth.middleware import MiddlewareMixin
from django.urls import reverse
from django.shortcuts import redirect, HttpResponse
from www import models
class AuthMiddleware(MiddlewareMixin):
def process_request(self, request):
if request.path_info in [reverse("login")]:
return
user_dict = request.session.get("user_session_key")
if not user_dict:
return redirect("login")
request.user_dict = user_dict
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, callback, *args, **kwargs):
if request.path_info in [reverse("login")]:
return
if request.user_dict["is_super"]:
menus = models.Menu.objects.all().values("id", "title", "permissions__name", "permissions__code")
request.menu_list = menus
return
# 用户访问的rl
url_name = request.resolver_match.url_name
print("PermissionMiddleware中间件: ", url_name)
# 用户对象
user_object = models.User.objects.filter(id=request.user_dict['id']).first()
# 获取当前用户的所有菜单
menus = models.Menu.objects.filter(user=user_object).values("id", "title", "permissions__name", "permissions__code")
request.menu_list = menus
# 用户所有的角色,角色对应的权限
user_per_list = user_object.roles.all().values("permissions__code", "permissions__name")
permission_dict = {item["permissions__code"]: item["permissions__name"] for item in user_per_list}
print("PermissionMiddleware中间件: ", permission_dict)
request.permission_dict = permission_dict
if url_name in permission_dict:
return
return HttpResponse("无权访问")
知识点巩固:
html用法:width、height、{% url “user_add” %}、母版的引用、
model的跨表查询,__str__用法,