我如何使用Django的MultiWidget?

时间:2010-08-18 12:07:49

标签: django django-widget 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小部件吗?

2 个答案:

答案 0 :(得分: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
  • 实现了一个在a中创建多个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使用此表单从所有提交数据的数据字典中提取与此窗口小部件关联的值。对于表示单个字段的多窗口小部件,您需要从多个子窗口小部件重建该值,这是数据的提交方式。
  • 如果您想使用django的媒体表示检索媒体,
  • _get_media可能对您有用。默认实现循环请求媒体的小部件;如果你继承它并使用任何花哨的小部件你需要调用超级;如果您的小部件需要任何媒体,那么您需要使用此添加它。

例如,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 :(得分:0)

仔细阅读此blog entry和相关的Django snippet。希望这会给你一些想法。