我如何使用Django的MultiWidget?

有关这个function的文档有点缺乏。

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] 

我可以看到我需要创build一个“小部件”属性与其他小部件的列表,但之后它得到一点福尔摩斯。

有人请向我解释如何使用MultiWidget小部件?

有趣的问题,我想也许值得在文档中多一点关注。

以下是我刚才问的一个问题的例子:

 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
  • 实现了一个构造函数,可以在元组中创build多个widgets.WidgetName小部件。 这很重要,因为超类使用这个元组的存在来为你处理几件事情。
  • 我的格式输出是传递,但想法是,你可以在这里添加自定义的HTML在你想要的
  • 我也实现了解decompress因为你必须 – 你应该期望从一个单一的value对象的数据库中传递值。 decompress打破这个小部件显示。 你在这里怎么做什么取决于你。

我没有,但可以有,重写:

  • render ,这实际上是负责渲染小部件,所以如果你inheritance这个,你肯定需要调用超级渲染方法。 通过inheritance这个东西,你可以在渲染之前改变事物的显示方式。

例如,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 – 在这里看到我的问题。 value_from_datadict使用此表单将与此窗口小部件关联的值从所有提交的数据的数据字典中提取出来。 对于代表单个字段的multiwidget,您需要从多个子小部件中重build该值,这就是数据如何提交的。
  • 如果您想使用django的媒体表示来检索媒体, _get_media可能对您有用。 默认实现循环小部件请求媒体; 如果你inheritance它,并使用任何花哨的小部件,你需要调用超级; 如果你的小部件需要任何媒体,那么你需要使用它来添加它。

例如, 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) 

同样,它正在创build一个到正确位置的path元组,正如我的小部件在__init__方法中创build了一个小部件元组。

我认为它涵盖了MultiWidget类的重要部分。 你要做什么取决于你创build了什么/你正在使用哪些小部件,这就是为什么我不能轻松地进入细节。 但是,如果您想自己查看基类,并查看注释,请查看源代码 。

通读这个博客条目和相关的Django 片段 。 希望这给你一些想法。