• rbac组件之权限操作(四)


    对于权限表的操作有两种方式,第一种是一个个的权限进行curd,另外一种是批量操作,自动发现django程序中的路由,进行批量curd,首先介绍第一种方式。

    因为在列出菜单时,已经将权限列表列出来了,所以权限包括增加、修改以及删除操作

    urls.py

    ...
        re_path(r'^permissions/add/$', PermissionAddView.as_view(), name='permissions_add'),
        re_path(r'^permissions/edit/(?P<pid>d+)/$', PermissionEditView.as_view(), name='permissions_edit'),
        re_path(r'^permissions/dell/(?P<pid>d+)/$', PermissionDelView.as_view(), name='permissions_del'),
        re_path(r'^multi/permissions/$', multi_permissions, name='multi_permissions'),
    ...

    后台进行处理

    from django import forms
    from rbac import models
    
    class PermissionModelForm(forms.ModelForm):
    
        class Meta:
            model=models.Permission
            fields='__all__'
    
            widgets = {
                'title': forms.TextInput(attrs={'placeholder': '请输入权限名称', 'class': 'form-control'}),
                'url': forms.TextInput(attrs={'placeholder': '请输入url', 'class': 'form-control'}),
                'name': forms.TextInput(attrs={'placeholder': '请输入url名称', 'class': 'form-control'}),
                'parent': forms.Select(attrs={'class': 'form-control'}),
                'menu':forms.Select(attrs={'class': 'form-control'}),
            }
            help_texts={
                'parent':'父级权限,无法作为菜单的权限才需要选择。',
                'menu':'选中,表示该权限可以作为菜单;否则,不可做菜单。'
            }
            error_messages ={
                'title':{
                        'required':'该字段不能为空'
                }
            }
    
        def clean(self):
            menu=self.cleaned_data['menu']
            parent=self.cleaned_data['parent']
            if menu and parent:
                self.add_error('menu','菜单和根权限同时只能选择一个')#错误标注在menu字段旁边
    PermissionModelForm
    from django.shortcuts import render,redirect,HttpResponse
    from django.views import View
    from rbac.models import *
    from rbac.forms.permissions import PermissionModelForm
    from django.urls import reverse
    
    
    class PermissionAddView(View):
        def get(self,request):
            form = PermissionModelForm()
            return render(request,'rbac/permission_add.html',{'form':form})
    
        def post(self,request):
            form=PermissionModelForm(data=request.POST)
            if form.is_valid():
                form.save()
                return redirect(reverse('rbac:menus_list'))
            return render(request,'rbac/permission_add.html',{'form':form})
    
    class PermissionEditView(View):
    
        def get(self,request,pid):
            permission_obj=Permission.objects.filter(id=pid).first()
            if not permission_obj:
                return HttpResponse('该权限不存在')
            form=PermissionModelForm(instance=permission_obj)
            return render(request,'rbac/permission_edit.html',{'form':form})
    
        def post(self,request,pid):
            permission_obj=Permission.objects.filter(id=pid).first()
            form=PermissionModelForm(data=request.POST,instance=permission_obj)
            if form.is_valid():
                form.save()
                return redirect(reverse('rbac:menus_list'))
            return render(request, 'rbac/permission_edit.html', {'form': form})
    
    class PermissionDelView(View):
    
        def  get(self,request,pid):
            Permission.objects.filter(id=pid).first().delete()
            return redirect(reverse('rbac:menus_list'))

    第二种方式是批量增加

    class MultiPermissionForm(forms.Form):
        id = forms.IntegerField(
            widget=forms.HiddenInput(),
            required=False
        )
        title = forms.CharField(
            widget=forms.TextInput(attrs={'class': "form-control"})
        )
        url = forms.CharField(
            widget=forms.TextInput(attrs={'class': "form-control"})
        )
        name = forms.CharField(
            widget=forms.TextInput(attrs={'class': "form-control"})
        )
        menu_id = forms.ChoiceField(
            choices=[(None, '-----')],
            widget=forms.Select(attrs={'class': "form-control"}),
            required=False,
    
        )
    
        parent_id = forms.ChoiceField(
            choices=[(None, '-----')],
            widget=forms.Select(attrs={'class': "form-control"}),
            required=False,
        )
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
            self.fields['parent_id'].choices += models.Permission.objects.filter(parent__isnull=True).exclude(
                menu__isnull=True).values_list('id', 'title')
    
        def clean_parent_id(self):
            menu = self.cleaned_data.get('menu_id')
            parent_id = self.cleaned_data.get('parent_id')
            if menu and parent_id:
                raise forms.ValidationError('菜单和根权限同时只能选择一个')
            return parent_id
    MultiPermissionForm

     利用formset生成批量数据

    from rbac.forms.muti_permissions import MultiPermissionForm
    from django.shortcuts import render
    from django.forms import formset_factory,modelform_factory
    from rbac import models
    from rbac.services.routes import *
    
    
    def multi_permissions(request):
        """
        批量操作权限
        :param request:
        :return:
        """
        post_type = request.GET.get('type')
    
        MultiPermissionFormSet = formset_factory(MultiPermissionForm,extra=0)
    
        generate_formset = None
        update_formset = None
    
        if request.method == 'POST' and post_type == 'generate':
            print('request.post',request.POST)
            formset = MultiPermissionFormSet(request.POST)
            if formset.is_valid():
                for row_dict in formset.cleaned_data:
                    models.Permission.objects.create(**row_dict)
            else:
                generate_formset = formset
    
        if request.method == 'POST' and post_type == 'update':
            formset = MultiPermissionFormSet(request.POST)
            if formset.is_valid():
                for row_dict in formset.cleaned_data:
                    permission_id = row_dict.pop('id')
                    models.Permission.objects.filter(id=permission_id).update(**row_dict)
            else:
                update_formset = formset
    
        # 1.1 去数据库中获取所有权限
        # [{},{}]
        permissions = models.Permission.objects.all().values('id', 'title', 'url', 'name', 'menu_id', 'parent_id')
        # {'rbac:menu_list':{},'rbac:menu_add':{..}}
        permisssion_dict = OrderedDict()
        for per in permissions:
            permisssion_dict[per['name']] = per
    
        # 1.2 数据库中有的所有权限name的集合
        permission_name_set = set(permisssion_dict.keys())
    
    
        # 2.1 获取路由系统中所有的URL
        # {'rbac:menu_list':{'url':.... },,,}
        router_dict = get_all_url_dict(ignore_namespace_list=['admin',])
    
        for row in permissions:
            name = row['name']
            if name in router_dict:
                router_dict[name].update(row)
    
        # 2.2 路由系统中的所有权限name的集合
        router_name_set = set(router_dict.keys())
    
        # 需要新建:数据库无、路由有
        if not generate_formset:
            generate_name_list=router_name_set-permission_name_set
            generate_formset = MultiPermissionFormSet(
                initial=[row for name, row in router_dict.items() if name in generate_name_list]
            )
    
        # 需要删除:数据库有、路由无
        destroy_name_list = permission_name_set - router_name_set
        destroy_formset = [row for name, row in permisssion_dict.items() if name in destroy_name_list]
    
        # 需要更新:数据库有、路由有
        if not update_formset:
            update_name_list = permission_name_set.intersection(router_name_set)
            update_formset = MultiPermissionFormSet(
                initial=[row for name, row in router_dict.items() if name in update_name_list]
            )
    
        return render(
            request,
            'rbac/multi_permissions.html',
            {
                'destroy_formset': destroy_formset,
                'update_formset': update_formset,
                'generate_formset': generate_formset,
            }
        )
    View Code

    获取路由系统中的url

    import re
    from collections import OrderedDict
    from django.conf import settings
    from django.utils.module_loading import import_string
    from django.urls.resolvers import URLResolver, URLPattern
    
    def recursion_urls(pre_namespace, pre_url, valid_urlpattern_list, url_ordered_dict):
        """
        递归的去获取URL
        :param pre_namespace: namespace前缀,以后用户拼接name
        :param pre_url: url前缀,以后用于拼接url
        :param urlpatterns: 路由关系列表
        :param url_ordered_dict: 用于保存递归中获取的所有路由
        :return:
        """
        for item in valid_urlpattern_list:
            if isinstance(item, URLPattern):  # 非路由分发,讲路由添加到url_ordered_dict
                if not item.name:
                    continue
                if pre_namespace:
                    name = "%s:%s" % (pre_namespace, item.name,)
                else:
                    name = item.name
                if not item.name:
                    raise Exception('URL路由中必须设置name属性')
                url = pre_url + str(item.pattern)
                url_ordered_dict[name] = {'name': name, 'url': url.replace('^', '').replace('$', '')}
    
            elif isinstance(item, URLResolver):  # 路由分发,递归操作
                if pre_namespace:
                    if item.namespace:
                        namespace = "%s:%s" % (pre_namespace, item.namespace,)
                    else:
                        namespace = pre_namespace
                else:
                    if item.namespace:
                        namespace = item.namespace
                    else:
                        namespace = None
                recursion_urls(namespace, pre_url + str(item.pattern), item.url_patterns, url_ordered_dict)
    
    
    def get_all_url_dict(ignore_namespace_list=None):
        """
        获取项目中所有的URL(必须有name别名)
        :return:
        """
        ignore_namespace_list=ignore_namespace_list or []
        valid_urlpattern_list=[]
        url_ordered_dict = OrderedDict()
    
        urlpatterns_list= import_string(settings.ROOT_URLCONF).urlpatterns  # from luff.. import urls
    
        for urlpattern in urlpatterns_list:
            if isinstance(urlpattern, URLResolver):
                if urlpattern.namespace in ignore_namespace_list:
                    continue
                else:
                    valid_urlpattern_list.append(urlpattern)
            valid_urlpattern_list.append(urlpattern)
    
        recursion_urls(None, '/', valid_urlpattern_list, url_ordered_dict)  # 递归去获取所有的路由
    
        return url_ordered_dict
    View Code
  • 相关阅读:
    16进制节码解析
    批注:modbus_tkdefines.py
    <20211019> Win10不明原因丢失任务提示栏里的Wifi以及网络任务提示栏logo
    <20210926>log: 运行5年3个月的NAS硬盘更换
    Huggingface中的BERT模型的使用方法
    list变量和dict变量前面加*号
    Linux服务器登录阿里网盘下载和上传文件的方法
    【IDEA与git集成】
    【为什么要用 @param注解】
    【我的编程习惯与开发插件】
  • 原文地址:https://www.cnblogs.com/shenjianping/p/10960663.html
Copyright © 2020-2023  润新知