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,如果不引入,则新建数据在页面显示失败
     
     
     
     
     
  • 相关阅读:
    JAVA基础--函数和数组03
    JAVA基础--流程控制语句02
    xampp环境下,配置Zend Studio调试php(XDebug) 转摘:http://www.cnblogs.com/tuyithief/archive/2011/06/02/2068431.html
    mysql修改root密码和设置权限 转摘:http://www.cnblogs.com/wangs/p/3346767.html
    mysql 备份还原
    Git忽略已经跟踪的文件 转摘:http://blog.csdn.net/huguohuan/article/details/7380349
    adb]ADB server didn't ACK
    java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation getting while running test project?
    Debug your ASP.NET Application while Hosted on IIS
    wireshark 识别http的标准
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9175384.html
Copyright © 2011-2022 走看看