Как мне использовать MultiWidget от Django?

Документация немного отсутствует в отношении этой функции.

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]

Я вижу, что мне нужно создать свойство "widgets" со списком других виджетов, но после этого он получает немного Шерлока Холмса.

Кто-нибудь, пожалуйста, объясните мне, как использовать виджет MultiWidget?

2 ответа

Решение

Интересный вопрос, и я думаю, возможно, заслуживает немного больше внимания в документах.

Вот пример из вопроса, который я только что задал:

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 - Смотрите мой вопрос здесь. value_from_datadict извлекает значение, связанное с этим виджетом, из словаря данных всех представленных данных с помощью этой формы. В случае нескольких виджетов, представляющих одно поле, вам необходимо восстановить это значение из нескольких подвиджетов, то есть, как данные будут представлены.
  • _get_media может быть полезно для вас, если вы хотите получить медиафайлы, используя медиа представление django. Реализация по умолчанию циклически изменяет виджеты, запрашивая медиа; если вы создаете подкласс и используете модные виджеты, вам нужно вызвать super; если вашему виджету нужен какой-либо носитель, то вам нужно добавить его, используя это.

Например, виджет django от markitup делает это:

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 учебный класс. То, что вы пытаетесь сделать, зависит от того, что вы создали / какие виджеты вы используете, поэтому я не могу вдаваться в подробности. Однако, если вы хотите увидеть базовый класс для себя и взглянуть на комментарии, взгляните на источник.

Прочитайте эту запись в блоге и связанный фрагмент Django. Надеюсь, что это дает вам некоторые идеи.

Другие вопросы по тегам