Подтвердить что ты не робот

Как использовать 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]

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

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

4b9b3361

Ответ 1

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

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

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)

Что я сделал?

  • subclassed django.forms.widgets.MultiWidget
  • Реализован конструктор, который создает несколько виджетов widgets.WidgetName в кортеж. Это важно, потому что суперкласс использует существование этого кортежа, чтобы позаботиться о нескольких вещах для вас.
  • Мой выходной формат является сквозным, но идея состоит в том, что вы можете добавить пользовательский html здесь, если хотите
  • Я также реализовал decompress, потому что вам нужно - вы должны ожидать передачи значений из базы данных в одном объекте value. decompress разрывает это для отображения в виджетах. Как и что вы здесь делаете, зависит от вас и зависит от виджета.

Вещи, которые у меня нет, но могли бы, overriden:

  • render, это фактически отвечает за визуализацию виджетов, поэтому вам обязательно нужно вызвать метод супердальности, если вы подклассифицируете это. Вы можете изменить, как вещи отображаются непосредственно перед рендерингом, путем подклассификации этого.

Пример, django markitup метод render:

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

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

Ответ 2

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