zoukankan      html  css  js  c++  java
  • Xadmin弹出窗口

    需求分析:

    1.在添加页面的一对多和多对多字段后面加上+,点击+后,能显示出添加相应字段的窗口

    2.提交后窗口关闭,添加的内容显示到当前页面

    1.判断出当前字段是否为ForeignKey或ManyToManyField,

    如果是则在后面添加+,不是则不添加。如果不进行判断,每个字段后面都会有+

    {% for foo in form_obj %}
        <div class="form-group" style="position: relative">
            <label for="">{{ foo.label }}</label>
            {{  foo }}  <span> {{  foo.errors.0}}</span>
            <a><span style="font-size: 22px;color: #1b6d85;position: absolute;top: 27px;right:-23px">+</span></a>
        </div>
    {% endfor %}
    1.在add函数中渲染页面时进行判断:
    form_obj = DemoModelForm()
    for i in form_obj: i为每个字段对象
    print(type(i)) #<class 'django.forms.boundfield.BoundField'>
    打印后所有的字段对象类型均为<class 'django.forms.boundfield.BoundField'>
    导入 from django.forms.boundfield import BoundField查看其源码:
    class BoundField(object):
        def __init__(self, form, field, name):
            self.form = form
            self.field = field
            self.name = name
            self.html_name = form.add_prefix(name)
    根据源码分析,字段类型有可能在field中,打印查看
    from django.forms.boundfield import BoundField
        for i in form_obj:
            print(type(i.field))
    <class 'django.forms.fields.DateField'>
    <class 'django.forms.fields.DecimalField'>
    <class 'django.forms.models.ModelChoiceField'>
    <class 'django.forms.models.ModelMultipleChoiceField'>

    2.在后端对符合条件的对象设置属性:

    from django.forms.boundfield import BoundField
        from django.forms.models import ModelChoiceField
        for boundfield in form_obj:
            print(type(boundfield.field))
            #只要字段关系类型属于ModelChoiceField,那么就是ForeignKey或ManyToManyField
            #为这个字段对象设置属性,在前端页面通过这个属性值及进行相应设置
            if isinstance(boundfield.field,ModelChoiceField):
                boundfield.is_pop = True
    
        return render(request, 'add_view.html', locals())

    3.在前端通过其属性来加+

    <form action="" method="post" novalidate >
        {% csrf_token %}
        {% for foo in form_obj %}
            <div class="form-group" style="position: relative">
                <label for="">{{ foo.label }}</label>
                {{  foo }}  <span> {{  foo.errors.0}}</span>
                {% if foo.is_pop %}
                      <a "><span style="font-size: 22px;color: #1b6d85;position: absolute;top: 27px;right:-23px">+</span></a>
                {% endif  %}
    
            </div>
        {% endfor %}
        <input type="submit" class="btn btn-default">
    </form>
    前端中form_obj值对应后端的form_obj,foo对应boundfield,因此foo.is_pop=boundfield.is_pop

    2.点击+后,需要弹出对应的添加窗口。

    1.比如,点击出版社,弹出的应该是出版设的添加窗口
    点击作者,弹出的是作者的添加窗口。窗口的打开路径应该就是对应表的添加路径
    < a onclick = "pop('{{ url }}')" > < span> + < / span > < / a >
    2.需要根据当前这个字段,如果是publish,就找到Publish的添加数据路径,如果是authors,就找到Author表的数据添加路径
    找到对应表的添加路径,就需要知道该字段连接的表的app和小写的表名。
    在ModelForm中能通过字段关系得到该表的类
    print(boundfield.field.queryset.model) #<class 'app01.models.Publish'
    3.拿到app和表名后,通过反向解析找到publish或Author的添加路径,为了后续添加到当前操作页面,让窗口打开的网页加上参数
    显示这种形式Xadmin/app01/publish/add/?pop_id=id_publish
    以当前字段标签的id作为参数
    boundfield.auto_id 字段对象.auto_id 自动匹配到该id
    views.py 弹出窗口GET请求时的操作
    def add_view(self, request):
    form_obj = DemoModelForm()
            ###判断字段的类型###
            # print("form_obj是:",form_obj)
            from django.forms.boundfield import BoundField
            from django.forms.models import ModelChoiceField
            for boundfield in form_obj:
                print(type(boundfield.field))
                #只要字段关系类型属于ModelChoiceField,那么就是ForeignKey或ManyToManyField
                #为这个字段对象设置属性,在前端页面通过这个属性值及进行相应设置
                if isinstance(boundfield.field,ModelChoiceField):
                    boundfield.is_pop = True
                    #获得该字段连接的表和所在的app
                    print(boundfield.field.queryset.model) #<class 'app01.models.Publish'>
                    model_class=boundfield.field.queryset.model
                    app_name=model_class._meta.app_label
                    model_name=model_class._meta.model_name
                    #反响解析,得到该表添加数据的路径
                    url_name = "{}/{}_add".format(app_name, model_name)
                    url = reverse(url_name)
                    #获得该字段在页面上标签的id,自动匹配
                    print(boundfield.auto_id) #id_publish
                    boundfield.url=url+'?pop_id=%s'%boundfield.auto_id
    
            return render(request, 'add_view.html', locals())
    View Code
    form.HTML
    <form action="" method="post" novalidate >
        {% csrf_token %}
        {% for foo in form_obj %}
            <div class="form-group" style="position: relative">
                <label for="">{{ foo.label }}</label>
                {{  foo }}  <span> {{  foo.errors.0}}</span>
                #字段关系判断
                {% if foo.is_pop %}
                      <a onclick="pop('{{ foo.url }}')"><span style="font-size: 22px;color: #1b6d85;position: absolute;top: 27px;right:-23px">+</span></a>
                {% endif  %}
    
            </div>
        {% endfor %}
        <input type="submit" class="btn btn-default">
    </form>
     <script>
         function pop(url) {
             window.open(url,"","wdith=500,height=300,top=200,left=200")
         }
     </script>
    View Code

    3.add POST请求

    1.弹出对应添加窗口后,添加完数据提交后,要将数据添加到对应的库中。然后将数据返回到"大窗口"的页面上
    2.在使用ModelForm时,使用form_obj.save()就会自动保存,保存之后,需要做到是大窗口添加
    的数据不返回,小窗口添加的数据返回,怎么判断是页面添加还是窗口添加的
    3.在窗口返回路由时,为其配置了参数,可以通过判断这个参数是否存在,存在则是小窗口添加,就做返回数据的操作
    页面添加的地址:Xadmin/app01/book/add/
    小窗口添加的地址:/Xadmin/app01/author/add/?pop_id=id_authors
     if request.method=='POST':
                form_obj=DemoModelForm(request.POST)
                if form_obj.is_valid():
                    obj=form_obj.save()
                    #判断是页面添加还是窗口添加
                    pop_id=request.GET.get("pop_id")
                    if pop_id:
                        text=str(obj)  #文本内容为此对象str的返回值
                        #返回关闭窗口的页面
                        return render(request,"pop.html",locals())
                    else:
                        # return redirect(list_url)  #不能用,相当于在当前路径后面拼接
                        return redirect(se

    4.对关闭窗口页面的操作

    在关闭窗口之前,需要将在窗口中添加的出版社名字或者作者名字传到显示页面上,POST请求将loacls()传给了
    这个窗口关闭页面,在这个页面我们取到在显示页面需要的数据,如要新建对象的id显示的文本内容,添加到字段的id,
    pop.html
    <script>
        window.opener.bar("{{ obj.pk }}","{{ text }}","{{ pop_id }}");
        window.close()
    </script>

    5.在显示页面处理窗口关闭页面的数据

    <select name="publish" required="" id="id_publish">
      <option value=" " selected="">---------</option>
      <option value="2">昌平出版社</option>
      <option value="3">西二旗出版社</option>
      <option value="4">汇德出版社</option>
      <option value="5">天青烟雨出版社</option>
      <option value="6">江南出版社</option>
    </select>
    显示页面上出版社的代码如上,我们需要将添加的数据构成这种样式,<option value="2">昌平出版社</option>添加到select标签中
    <script src="/static/jquery-3.3.1.js"></script>
    <script>
        function bar(pk,text,pop_id){
            var $new_tag=$("<option></option>");
            $new_tag.html(text);
            $new_tag.attr("value",pk);
            {# 设置默认选中       #}
            $new_tag.attr("selected","selected"); 
            添加标签
            $("#"+pop_id).append($new_tag)
        }
    </script>
    由于在创建标签时,使用的时jquery对象,因此要进入jquery-3.3.1.js,如果不引入,则新建数据在页面显示失败
     
     
     
     
     
  • 相关阅读:
    AcWing 157. 树形地铁系统 (hash判断树同构)打卡
    AcWing 156. 矩阵 (哈希二维转一维查询)打卡
    AcWing 144. 最长异或值路径 01字典树打卡
    AcWing 143. 最大异或对 01字典树打卡
    AcWing 142. 前缀统计 字典树打卡
    AcWing 139. 回文子串的最大长度 hash打卡
    AcWing 138. 兔子与兔子 hash打卡
    常用C库函数功能及用法
    编程实现C库函数
    C语言面试题5
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9175384.html
Copyright © 2011-2022 走看看