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,如果不引入,則新建數據在頁面顯示失敗
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM