Pregunta interesante y creo que quizás merezca un poco más de atención en los documentos.
He aquí un ejemplo de a question I've just asked:
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?
- subclases
django.forms.widgets.MultiWidget
- Implementado un constructor que crea varios
widgets.WidgetName
los 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 a través, pero la idea es que se puede añadir código HTML personalizada en caso de que deseen aquí
- también he implementado
decompress
porque hay que - usted debe esperar para pasar los valores de la base de datos en un solo objeto value
. decompress
divide esto para mostrarlo en el widget. Cómo y qué haces aquí depende de ti y depende del widget.
Cosas que no tienen, pero podría tener, anulado:
render
, esto es realmente responsable de la prestación de los widgets, por lo que sin duda tendrá que llamar a la súper render método si subclase esto. Puede cambiar cómo se muestran las cosas justo antes de renderizar subclasando esto.
ejemplo, Django markitup 's render método:
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
- Ver 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 si desea recuperar medios utilizando 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, widget de Django markitup 's 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)
Una vez más, se está creando una tupla de calzadas para la ubicación correcta, al igual que mi aparato ha creado una tupla de widgets en el __init__
método.
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 sí mismo y echar un vistazo a los comentarios, eche un vistazo al the source.
Esta solución es un poco pirata, pero está más en línea con la forma en que esperamos acceder a los subcampos en la plantilla. http://stackoverflow.com/questions/24866936/render-only-one-part-of-a-multiwidget-in-django – farthVader