Comment utiliser le MultiWidget de Django?
la documentation est un peu insuffisante en ce qui concerne cette caractéristique.
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]
je peux voir que j'ai besoin de créer une propriété" widgets " avec une liste d'autres widgets, mais après cela il obtient un peu Sherlock Holmes.
est-ce que quelqu'un pourrait m'expliquer comment utiliser le widget MultiWidget?
2 réponses
question intéressante et je pense peut-être mériter un peu plus d'attention dans les docs.
voici un exemple de une question que je viens de poser :
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-classe
django.forms.widgets.MultiWidget
- mis en œuvre un constructeur qui crée plusieurs
widgets.WidgetName
widgets dans un tuple. C'est important parce que la classe super utilise l'existence de ce n-uplet de prendre soin de plusieurs choses pour vous. - Mon format de sortie est pass-through, mais l'idée est que vous pouvez ajouter HTML personnalisé ici si vous le souhaitez
- j'ai aussi implémenté
decompress
parce que vous devez - vous attendre à passer des valeurs de la base de données dans un seul objetvalue
.decompress
décompose cela pour affichage dans le widget. Comment et ce que vous faites ici est à vous et dépend du widget.
les choses que je n'ai pas, mais que je pourrais avoir, l'emportent:
-
render
, ceci est en fait responsable du rendu des widgets, donc vous devez certainement appeler la méthode super render si vous sous-classez ceci. Vous pouvez changer la façon dont les choses sont affichées juste avant le rendu en sous-classant ceci.
, par Exemple, django markitup 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 seul champ, vous devez reconstruire cette valeur à partir de vos multiples sous-widgets, ce qui est la façon dont les données auront été soumises. -
_get_media
peut être utile pour vous si vous voulez récupérer des médias utiliser la représentation des médias par django. L'implémentation par défaut cycle les widgets demandant les médias; si vous les sous-classez et utilisez des widgets de fantaisie, vous devez appeler le super; si votre widget a besoin d'un média, alors vous devez l'ajouter en utilisant ceci.
Par exemple, markitup django widget ne 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, il crée un nuage de chemins à l'endroit correct, tout comme mon widget a créé un tuple de widgets dans la méthode __init__
.
je pense que cela couvre les parties importantes de la classe MultiWidget
. Ce que vous essayez de faire dépend de ce que vous avez créé/quels widgets vous utilisez, c'est pourquoi je ne peux pas entrer dans les détails facilement. Cependant, si vous voulez voir la classe de base pour vous-même et jeter un oeil aux commentaires, jetez un oeil à la source .
lire à travers cette entrée de blog et le Django associé snippet . Espérons que cela vous donne quelques idées.