form - ¿Cómo uso el MultiWidget de Django?
modelform widgets django (2)
La documentación es un poco escasa con respecto a esta característica.
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]
Puedo ver que necesito crear una propiedad de "widgets" con una lista de otros widgets, pero luego se pone un poco de Sherlock Holmes.
¿Alguien podría explicarme cómo usar el widget MultiWidget?
Interesante pregunta y creo que tal vez merezca un poco más de atención en los documentos.
Aquí hay un ejemplo de una pregunta que acabo de hacer :
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é he hecho?
- subclase
django.forms.widgets.MultiWidget
- Implementé un constructor que crea varios widgets. Widgets de widgets en una tupla. Esto es importante porque la súper clase usa la existencia de esta tupla para ocuparse de varias cosas por ti.
- Mi salida de formato es de paso, pero la idea es que puede agregar html personalizado aquí si lo desea
- También implementé la
decompress
porque es necesario; debe esperar que se pasen valores de la base de datos en un único objeto devalue
.decompress
divide para mostrarlo en el widget. Cómo y qué haces aquí depende de ti y depende del widget.
Cosas que no he, pero podría haber, anuladas:
-
render
, esto es realmente responsable de renderizar widgets, por lo que definitivamente debe llamar al método de renderizado super si lo subclase. Puede cambiar cómo se muestran las cosas justo antes de renderizar subclasando esto.
Ejemplo, el método de renderizado de django markitup :
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
- Vea mi pregunta here . value_from_datadict extrae el valor asociado con este widget del diccionario de datos de todos los datos enviados con este formulario. En el caso de un multiwidget que representa un solo campo, debe reconstruir ese valor a partir de sus múltiples subwidgets, que es cómo se han enviado los datos. -
_get_media
puede ser útil para ti si quieres recuperar medios usando la representación de medios de django. La implementación predeterminada cicla los widgets que solicitan los medios; si lo subclases y estás usando cualquier widgets elegante, debes llamar al súper; si su widget necesita algún medio, entonces necesita agregarlo usando esto.
Por ejemplo, el widget django de markitup hace esto:
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)
De nuevo, está creando una tupla de rutas hacia la ubicación correcta, del mismo modo que mi widget ha creado una tupla de widgets en el método __init__
.
Creo que lo cubre partes importantes de la clase MultiWidget
. Lo que estás tratando de hacer depende de lo que hayas creado / qué widgets estés usando, por lo que no puedo entrar en detalles fácilmente. Sin embargo, si desea ver la clase base por su cuenta y echar un vistazo a los comentarios, eche un vistazo a la fuente .
Lea esta entrada de blog y el snippet Django asociado. Espero que esto te dé algunas ideas.