2010-03-01 51 views
18

這裏是我做的方式:你會如何在Django中創建一個動態的formset?

{{ formset.management_form }} 
<table> 
    {% for form in formset.forms %} 
     {{ form }} 
    {% endfor %} 
</table> 
<a href="javascript:void(0)" id="add_form">Add Form</a> 

而這裏的JS:

var form_count = {{formset.total_form_count}}; 
$('#add_form').click(function() { 
    form_count++; 
    var form = '{{formset.empty_form|escapejs}}'.replace(/__prefix__/g, form_count); 
    $('#forms').append(form) 
    $('#id_form-TOTAL_FORMS').val(form_count); 
}); 

具體什麼困擾我的是,我不得不寫escapejs模板標籤自己。它只是去除所有換行符,並且轉義任何單引號,這樣它就不會弄亂我的字符串。但是,在這種情況下,Django製造商究竟希望我們做什麼?爲什麼他們有這個隱藏字段,他們可能剛剛使用了一個像<input name="my_form_field[0]" />這樣的數組,然後計算它的長度呢?

+1

但是,你爲什麼要混合django模板和JavaScript? – Prashanth 2010-03-01 04:38:37

+0

以便我可以處理它。否則,我必須在視圖中完全自定義表單處理。 Django似乎鼓勵這種方法,那就是*爲什麼*他們提供了這個'empty_form'和'__prefix__',以便你可以替換它。 – mpen 2010-03-01 06:36:02

+1

我喜歡'.empty_form'的用法 - 很好,很短。謝謝! – 2011-05-24 01:09:26

回答

5

在Django中有一些地方「爲什麼」是因爲它是如何在Django管理應用程序中實現的,我相信這就是其中之一。因此,答案是他們期望你實現你自己的JavaScript。

查看此SO問題Dynamically adding a form...瞭解更多javascript的想法。

還有兩個可插拔的應用程序可用,django-dynamic-formsetdjango-dinamyc-form,直到現在才查看第一個。

+1

編寫我自己的JS並不是一個真正的問題......我只是好奇他們爲什麼只給我們一半的工具,我們需要......他們說'empty_form'可以是用於這個,但它打印線斷行和這樣的東西不是很友好的時候嘗試填充到JS,除非我誤解了一些東西。我認爲我更喜歡我的動態formset方法...我懷疑它會減少客戶端的壓力,並且需要更少的代碼:)噢,好吧......我想我只是挑剔,但我仍然真的很不贊同Django的設計決策。 – mpen 2010-03-02 02:39:47

+0

好的,Django恰當的設計決策是保持JS框架中立。管理員是一個contrib應用程序,所以在技術上不是Django核心的一部分,雖然一些功能,如formset(顯然)來自於管理員的工作,而我認爲管理員是一個很好的應用程序,它可能會受到一定程度的影響從缺乏宏偉的設計。 – 2010-03-02 07:58:26

+3

如果你想用ajax做任何事情或動態添加新對象,Formset是一個巨大的痛苦。 Django嘗試設計Web 2.0類型應用程序時,迄今爲止最大的問題。出於這個原因,我們在Django投資了6個月後,幾乎改用了Java框架,但決定花費太多時間。 – 2011-11-02 06:19:28

4

這個問題有點舊了,但我花了一段時間才弄清楚了。

我建議將模板中的formset.empty_form呈現爲隱藏字段,並在JavaScript中引用此字段。

下面是來自Django管理站點一個複雜的動態表單集例如: (但要注意,它並沒有被更新爲使用empty_form ....)

[JS] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js

[HTML模板] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html

+0

我最近(實際上幾個小時前)redid這個...它真的討厭與...一起工作嘗試添加和刪除窗體,並更新所有分散的ID,並確保至少有一個窗體,並驗證他們都正確...與ajax/cascading/contingent選擇下拉菜單相結合,它成爲一個微型的噩夢。 – mpen 2010-08-11 01:40:19

+0

你有沒有從django inlines.js例子中工作?我爲我的網站進行了修改(希望在單獨的列表中添加按鈕)。不是微不足道的(我是js新手,所以需要一段時間),但我想我設法將大部分邏輯包含在一個獨立的腳本中。 – bsk 2010-08-11 19:17:01

1

這是因爲formset已創建工作沒有JavaScript,只使用通常的HTTP工作流程。

Django是javascript不可知論者。

如果你想添加一些javascript的混合,你可以使用dedicated jquery plugin

+1

希望我能看到演示,但謝謝。 Django的設計目的是在沒有JavaScript的情況下工作,是的,但它似乎有一些小的鉤子來構建JavaScript ....我只是希望他們更進一步,因爲這很痛苦。 – mpen 2012-01-04 22:37:53

+0

@Mark:實際上有一個演示:-)在http://code.google.com/p/django-dynamic-formset/下載該項目,它包含一個django演示。 – 2012-01-05 09:27:41

+0

這不是我演示的意思。我的意思是不必下載它(「現場演示」?)。有數百萬個項目和程序在那裏......人們喜歡在投入時間和精力,下載和提取內容,和/或安裝/編譯之前知道他們得到了什麼。無論如何,既然你*推薦了它,它不僅僅是我偶然發現的一些隨機事物,我會檢查出來......(如果它是如此美妙的圖書館,你會期望它會在某個地方使用可以鏈接到...) – mpen 2012-01-05 16:32:29

1

在我的情況。我使用了插件django-dynamic-formset(https://code.google.com/p/django-dynamic-formset/wiki/Usage

並修改了選項「added」並且運行良好。

 $('#formset-table tbody tr').formset({ 
      prefix: '{{ formset.prefix }}', 
      formCssClass: '{{ formset.prefix }}-inlineformset', 
      added: function(obj_tr){ 
   var form = $(obj_tr).html().replace(/\-(\w+)\-(\w+)(fix__)\-/g, '-'); 
       $(obj_tr).html(form); 

      }, 

這個正則表達式替換字符串[前綴] - 前綴同行 ' - '

也許不是最好的解決辦法,但工作。

1

當使用formset.empty_form作爲字符串時,有一些可能的XSS的情況,將'__prefix__'替換爲實際的formset表單索引。我的可插入應用程序將formset.empty_form轉換爲Knockout.js模板,然後通過自定義Knockout.js綁定進行克隆。此外,Knockout.js會自動重新計算表單字段標識索引,當在添加inlineformsets的整個表單提交之前動態刪除新添加的表單集表單表單時。下面是文檔:加載與內嵌的JavaScript自定義字段時

https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms

Knockout.js還結合防止XSS。

相關問題