web-dev-qa-db-ja.com

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ウィジェットの使用方法を誰かに説明してもらえますか?

46
John Mee

興味深い質問で、おそらくドキュメントでもう少し注目するに値すると思います。

これは、 たった今の質問の例です

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 の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クラスの重要な部分については、これでカバーできると思います。あなたがやろうとしていることは、あなたが作成したもの/あなたが使用しているウィジェットに依存します、それが私が簡単に詳細に入ることができない理由です。ただし、基本クラスを自分で確認してコメントを確認したい場合は、 source を確認してください。

51
user257111

この ブログエントリ と関連するDjango snippet を読んでください。これがあなたにいくつかのアイデアを与えることを願っています。

0
Manoj Govindan