Question intéressante et je pense que peut-être bénéficier d'un peu plus d'attention dans les docs.
Voici un exemple d' une question que j'ai juste demandé:
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)
Qu'ai-je fait?
- sous-classé
django.forms.widgets.MultiWidget
- Mise en œuvre d'un constructeur qui crée plusieurs
widgets.WidgetName
widgets dans un
n-uplet. Ceci est important parce que la super-classe utilise l'existence de ce n-uplet de prendre soin de plusieurs choses pour vous.
- Mon format de sortie est le pass-through, mais l'idée est que vous pouvez ajouter votre propre code html ici si vous le souhaitez
- J'ai également mis en œuvre
decompress
parce que vous avez - vous devriez vous attendre à être transmis les valeurs de la base de données dans un seul value
objet. decompress
casse ce jusqu'à afficher dans le widget. Comment et ce que vous faites ici est à vous et dépend du widget.
Choses que je n'ai pas, mais qui aurait pu, bien sûr:
-
render
, c'est en fait responsables pour le rendu des widgets, alors vous avez certainement besoin d'appeler le super méthode render si vous sous-classe cet. Vous pouvez changer la façon dont les choses sont affichés juste avant le rendu par ce sous-classement.
Exemple, django markitup's méthode de rendu:
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
- Voir ma question ici. value_from_datadict tire la valeur associée à ce widget hors du dictionnaire de données de toutes les données envoyées avec ce formulaire. Dans le cas d'un multiwidget représentant un champ unique, vous avez besoin de reconstruire que de la valeur de vos multiples sous-widgets, qui est la façon dont les données ont été soumises.
-
_get_media
pourrait être utile pour vous, si vous souhaitez récupérer les médias à l'aide de django reinhardt, de la représentation des médias. La valeur par défaut de la mise en œuvre des cycles de widgets de demander, pour les médias; si vous sous-classe et à l'aide de toute fantaisie widgets, vous devez appeler le super; si votre widget besoins de tous les médias, alors vous devez ajouter à l'aide de ce.
Par exemple, markitups'django widget fait ceci:
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)
Encore une fois, c'est la création d'un tuple de chemins d'accès à l'emplacement correct, tout comme mon widget a créé un tuple de widgets dans l' __init__
méthode.
Je pense que pour des parties importantes de l' MultiWidget
classe. Ce que vous voulez faire dépend de ce que vous avez créés ou qui les widgets que vous utilisez, c'est pourquoi je ne peux pas aller dans les détails facilement. Toutefois, si vous voulez voir la classe de base pour vous-même et de prendre un coup d'oeil sur les commentaires, jetez un oeil à la source.