2010-08-18 53 views
43

有關此功能的文檔有點缺乏。如何使用Django的MultiWidget?

from django import forms 

class TwoInputWidget(forms.MultiWidget): 
    """An example widget which concatenates two text inputs with a space""" 
    def __init__(self, attrs=None): 
     widgets = [forms.TextInput, forms.TextInput] 

我可以看到我需要創建與其他部件列表的「小工具」屬性,但在那之後就有點福爾摩斯。

有人請向我解釋如何使用MultiWidget小部件?

+0

這個解決方案有點破解,但更符合我們期望訪問模板中子域的方式。 http://stackoverflow.com/questions/24866936/render-only-one-part-of-a-multiwidget-in-django – farthVader 2016-06-28 21:21:59

回答

51

有趣的問題,我想也許值得在文檔中多一點關注。

下面是a question I've just asked一個例子:

class DateSelectorWidget(widgets.MultiWidget): 
    def __init__(self, attrs=None, dt=None, mode=0): 
     if dt is not None: 
      self.datepos = dt 
     else: 
      self.datepos = date.today()  

     # bits of python to create days, months, years 
     # example below, the rest snipped for neatness. 

     years = [(year, year) for year in year_digits] 

     _widgets = (
      widgets.Select(attrs=attrs, choices=days), 
      widgets.Select(attrs=attrs, choices=months), 
      widgets.Select(attrs=attrs, choices=years), 
      ) 
     super(DateSelectorWidget, self).__init__(_widgets, attrs) 

    def decompress(self, value): 
     if value: 
      return [value.day, value.month, value.year] 
     return [None, None, None] 

    def format_output(self, rendered_widgets): 
     return u''.join(rendered_widgets) 

搞什麼名堂我做了什麼?

  • 子類django.forms.widgets.MultiWidget
  • 實現,在一個 元組創建幾個widgets.WidgetName部件的構造函數。這很重要,因爲超類使用這個元組的存在來爲你處理幾件事情。
  • 我的格式輸出直通,但這個想法是,你可以添加自定義HTML在這裏,你應該希望
  • 我也實現decompress因爲你必須要 - 你應該會從數據庫中傳遞的值在一個單一的value對象中。 decompress將其分解以顯示在小部件中。你在這裏做什麼和做什麼取決於你,取決於小部件。

事情我沒有,但可以有,重寫:

  • render,這是使部件實際負責,所以你一定要打電話,如果你這個子類的超級渲染方法。通過繼承這個東西,你可以在渲染之前改變事物的顯示方式。

例,Django的markitup的渲染方法:

def render(self, name, value, attrs=None): 
    html = super(MarkItUpWidget, self).render(name, value, attrs) 

    if self.auto_preview: 
     auto_preview = "$('a[title=\"Preview\"]').trigger('mouseup');" 
    else: auto_preview = '' 

    html += ('<script type="text/javascript">' 
      '(function($) { ' 
      '$(document).ready(function() {' 
      ' $("#%(id)s").markItUp(mySettings);' 
      ' %(auto_preview)s ' 
      '});' 
      '})(jQuery);' 
      '</script>' % {'id': attrs['id'], 
          'auto_preview': auto_preview }) 
    return mark_safe(html) 
  • value_from_datadict - 見我的問題here。 value_from_datadict使用此表單將與此窗口小部件關聯的值從所有提交的數據的數據字典中提取出來。對於代表單個字段的multiwidget,您需要從多個子小部件中重建該值,這就是數據如何提交的。
  • _get_media可能對您有用,如果您想使用django的媒體表示檢索媒體。默認實現循環小部件請求媒體;如果你繼承它並使用任何奇特的小部件,你需要調用超級;如果你的小部件需要任何媒體,那麼你需要使用它來添加它。

例如,markitup的Django的插件做到這一點:

def _media(self): 
     return forms.Media(
      css= {'screen': (posixpath.join(self.miu_skin, 'style.css'), 
          posixpath.join(self.miu_set, 'style.css'))}, 
      js=(settings.JQUERY_URL, 
       absolute_url('markitup/jquery.markitup.js'), 
       posixpath.join(self.miu_set, 'set.js'))) 
    media = property(_media) 

再次,這是創造的路徑的元組到正確的位置,就像我的小部件創建的小部件的元組在__init__方法。

我認爲它涵蓋了MultiWidget類的重要部分。你試圖做的事情取決於你創建的東西/你使用的是哪些小部件,這就是爲什麼我無法輕鬆進入細節的原因。但是,如果您想自己查看基類並查看評論,請查看the source

+1

絕對是迄今爲止我所見過的創建多窗口小部件表單字段的最佳主題指南,我相信我已經見過不少! – 2011-01-17 22:48:31

+0

您能否提供一個如何在模型窗體中使用多窗口小部件的示例?或者是多窗口小部件設計爲拆分不合並它們的字段? – 2016-09-18 19:34:52

+0

'format_output'方法已被棄用,並且不再存在於Widget類中。 – Cerin 2017-11-03 19:43:16

0

通讀此blog entry和相關的Django snippet。希望這給你一些想法。

+0

謝謝。該片段確實提供了更多線索。但它仍然是偵探工作。我通過閱讀代碼並查看示例來收集如何使用它。我仍然希望已經解決了這個謎團的人能夠爲我們提供一些如何使用的指導。 – 2010-08-19 08:26:51