• 权限分配之一级菜单保留原搜索条件


    如何一直携带 当前GET请求中, ?mid=1&age=2&name=alex
    先看一看问题的产生:
    1.我的菜单列表页面,当我点击,某一个菜单选项时。会发送一个GET请求,并且将当前这个菜单的 id 发送到服务端。
    服务端进行页面渲染时, 会为这个菜单添加一个,calss="active":
    看代码:

                            <tr class="{% if menu_id == menu.pk|safe  %}active{% endif %}">
                                <th><a href="?mid={{ menu.pk }}">{{ menu.title }}</a></th>
                                <td><i class="fa {{ menu.icon }}" aria-hidden="true"></i></td>
                                <td>
                                    <a style="color: #333333;" href="{% url 'rbac:menu_edit' pk=menu.pk %}">
                                        <i class="fa fa-edit" aria-hidden="true"></i></a>
                                    <a style="color: #d9534f;" href="{% url 'rbac:menu_del' pk=menu.pk %}"><i
                                            class="fa fa-trash-o"></i></a>
                                </td>
                            </tr>
    原 菜单列表,页面, menu_list.html

    视图函数中:

    def menu_list(request):
        '''
        菜单和权限列表
        :param request:
        :return:
        '''
        # menu_id = int(request.GET.get("mid"))  # 前端判断时,需要一个int类型,而不是str类型。
        menu_id = request.GET.get("mid")  # 或者在前端进行转换,将数字转换成,字符串
        menu_list = models.Menu.objects.all()
        return render(request, "rbac/menu_list.html", locals())
    
    def menu_add(request):
        '''
        添加页面
        :param request:
        :return:
        '''
        if request.method == "POST":
            forms = MenuForm(request.POST)
            if forms.is_valid():
                forms.save()
                return redirect("rbac:menu_list")  # 这里需要做更改
            else:
                return render(request, "rbac/change.html", {"forms": forms})
        forms = MenuForm()
        return render(request, "rbac/change.html", {"forms": forms})
    

    视图函数中,无需更改。  我需要做的就是,在模板中,生成url的时候,要做一些改动。
    比如:
      我当前的菜单列表url                       http://127.0.0.1:8000/rbac/menu/list/?mid=1
      进入添加菜单url :  http://127.0.0.1:8000/rbac/menu/add/?_filter=mid%3D1
    这就是我想要的效果:
      当前菜单列表,有 mid=1 的参数。 而我想做的就是,进入下一个页面的时候, 将mid=1 这个参数给携带上。
      但是又不能够直接就 拼接在后面, 因为如果我的添加页面,在提交数据的时候 也有一个参数是  mid=1 那么, 服务端  就不能够进行处理。
      所以, 我将 mid=1  进行转义打包成  _filter=mid%3D1。 单独使用一个变量来接收我想要的真实数据。

    来看看如何实现:
      1.要想实现的话, 就要在服务端进行渲染页面时。 在对url 反向解析时,进行处理。
      原来我是使用    <a href="{% url  'rbac:menu_add' %}">添加菜单</a>。 这样的做法,只能够解析出这个url的地址,但  是却不能够, 携带上我的  mid=1  这个参数。
      他解析出来是  http://127.0.0.1:8000/rbac/menu/add/  这个样子的。
      但是我需要的是    http://127.0.0.1:8000/rbac/menu/add/?_filter=mid%3D1  这个样子的。
      2.  so 定义一个模板语法吧:
      这个模板语法需要的参数, 一定要 request  因为我需要从request对象中, 取得当前GET请求中携带的参数 mid=1。
      然后是  'rbac:menu_add'  我需要这个名字,进行  reverse() 反向解析出。我要进入的这个url。 最后还有一点, 是针对   带有正则的  url  。 针对这种 url  在反向解析的时候, 必须要提供给reverse() 方法。这个参数。
      比如:re_path(r"^menu/edit/(?P<pk>d+)/$", menu.menu_edit, name="menu_edit"),
      在反向解析的时候  就需要  reverse("rbac:menu_edit", 12)  后面根的是什么,取决于正则是怎么写的。
      然后有一点要注意的是, 如果是 /(?P<pk>d+)/ 这就是有名分组, 传参数时就是, 关键字传参。
      如果是 /(d+)/ 这就是无名分组, 传参数时就是, 位置参数传参。
    基于以上的理由,进行, 这个自定义模板的编写:

    def memory_url(request, name, *args, **kwargs):
        '''
        生成带有原搜索条件的url  (?mid=1&age=20)  (替代原模板中的url)
        :param request:  # 从request中获取,当前请求的所有参数
        :param name:  # 帮助反向解析,生成url  'rbac:menu_list'
        :return:
        '''
        basic_url = reverse(name, args=args, kwargs=kwargs)
        # basic_url = reverse(name, kwargs="", args="")
        # reverse中使用kwargs传参,或者使用args传参, 取决于在url路由分发的阶段, 正则表达式 是关键字传参还是位置传参
    
        # 当前GET请求的url中无参数,携带。直接返回 反向解析的,地址
        if not request.GET:
            return basic_url
        # 当前GET请求的url中有参数,携带。 那么就需要将,这次请求的url 中的参数。进行打包,传给下一次的url
        query_dict = QueryDict(mutable=True)  # 使用django自带的Query_Dict 进行参数的打包。
        query_dict["_filter"] = request.GET.urlencode()  # 获取到本次GET请求携带的数据mid=2 。 并交给QueryDict进行转义打包
        # query_dict.urlencode()  # 这里就会使自动转义之后的字符串 _filter=mid%3D1
        return "%s?%s" % (basic_url, query_dict.urlencode())

    reverse(name, args=args, kwargs=kwargs) 先对,基础的路由地址url 进行解析。

    判断,当前请求中, 是否有参数携带。    request.GET 如果是 None 的话, 就说明没有参数携带, 也就不需要进行把参数携带到下一个路由当中了。

    使用Django自带的QueryDict, 来打包我们的参数。 理由上述已经讲过。
    如果有参数携带的话, 最终返回的, 就是携带了参数的  一条完整的 url

    模板中的使用:

                    <div class="panel-heading"><i class="fa fa-book" aria-hidden="true"></i> 一级菜单
                        <a href="{% memory_url request 'rbac:menu_add' %}" class="right btn btn-success btn-xs"
                           style="padding: 2px 8px;margin: -3px;">
                            <i class="fa fa-plus-circle" aria-hidden="true"></i>
                            新建
                        </a>
                    </div>
    
    模板中需要填入的参数,只有 request  和  'rbac:menu_add'  。
    需要注意的是, 因为是位置传参, 这两个顺序是不能错的!
    menu_list.html


    然后最后一个问题了:
    我已经将,参数进行处理之后,携带这本次的  mid=1 进入到了。下一次的url中。
    那么, 往回跳转的时候呢?
    看代码:

    def memory_reverse(request, name, *args, **kwargs):
        '''
        反向生成url。
            1.在url获取原来的搜索条件, 如_filter之后的值
            2.reverse反向解析原来的url 如:/menu/list/
            3.进行拼接:/menu/list/?_filter=mid%3D2
        示例:
            http://127.0.0.1:8000/rbac/menu/add/?_filter=mid%3D2
        解析之后:
            http://127.0.0.1:8000/rbac/menu/list/?mid=2
        :param request:
        :param name:   # url的别名
        :param args:   # url中正则分组的位置参数
        :param kwargs: #url中正则分组的关键字参数
        :return:
        '''
        url = reverse(name, args=args, kwargs=kwargs)
        origin_params = request.GET.get("_filter")
        if origin_params:
            url = "%s?%s" % (url, origin_params)
        return url
    

     我们知道,在视图中跳转使用的是: redirect()
    比如  我在添加成功菜单成功之后的 视图函数是这样写的:

    def menu_add(request):
        '''
        添加页面
        :param request:
        :return:
        '''
        if request.method == "POST":
            forms = MenuForm(request.POST)
            if forms.is_valid():
                forms.save()
                return redirect(reverse("rbac:menu_list"))
            else:
                return render(request, "rbac/change.html", {"forms": forms})
        forms = MenuForm()
        return render(request, "rbac/change.html", {"forms": forms})
    

     看代码,可以看出。 也没什么不对。  但是如果单纯的这样写, 我自己的反向解析函数 momory_reverse() 不就白写了嘛!
    而且最重要的, 我想要的  ../?_filter=mid%3D1  这个 问号,后面的参数, 没有给我带过来。
    so:还是,使用。我的这个反向解析函数:

    def menu_add(request):
        '''
        添加页面
        :param request:
        :return:
        '''
        if request.method == "POST":
            forms = MenuForm(request.POST)
            if forms.is_valid():
                forms.save()
                return redirect(memory_reverse(request, "rbac:menu_list"))
            else:
                return render(request, "rbac/change.html", {"forms": forms})
        forms = MenuForm()
        return render(request, "rbac/change.html", {"forms": forms})
    

     让,我跳转向的, menu_list  的url  能够携带上。 进入添加页面之前时,我在 menu_list 页面 url中所有的 mid=1 这个参数。

    可能有些,难以理解。 不过举个例子就是:
      我在 菜单列表页面时,我的参数中有一个 mid=1
      然后 你带着这个 mid=1 到添加页面,逛了一圈。
      然后回来的时候, 你得把这个 mid=1 这个参数,还给我,    不能直接扔了。

     


      

  • 相关阅读:
    java验证身份证号码
    java两种定时器
    Nginx负载均衡配置
    python中import list,dictionary常量在class实例化时遇到的坑
    UnicodeDecodeError: 'gbk' codec can't decode byte 0xaf in position 218: illegal multibyte sequence解决方案
    jenkins+gradle打包android遇到的坑
    mac安装神器brew
    mac配置jenkins遇到的问题及解决办法
    django框架搭建web服务
    贯众云平台脚本编写之判断、循环以及shell命令的使用
  • 原文地址:https://www.cnblogs.com/chengege/p/10710371.html
Copyright © 2020-2023  润新知