興味深い質問であり、ドキュメントでもう少し注意を払う価値があると思います。
これは、私が今尋ねた質問の例です:
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を参照してください。