2010-08-18 13 views
43

La documentación es un poco escasa con respecto a esta característica.¿Cómo uso el MultiWidget de Django?

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 para crear una propiedad "widgets" con una lista de otros widgets, pero después de que se pone un poco Sherlock Holmes.

¿Podría alguien explicarme cómo usar el widget MultiWidget?

+0

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

Respuesta

51

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.

+1

Definitivamente la mejor guía de temas sobre la creación de campos de formulario de múltiples widgets que he visto hasta la fecha, ¡y creo que he visto bastantes! –

+0

¿Puede proporcionar un ejemplo de cómo usar un widget múltiple en un formulario modelo para dos campos en ese formulario? ¿O está diseñado para multi-widgets para dividir los campos y no combinarlos? –

+0

El método 'format_output' ha quedado obsoleto y ya no existe en la clase de Widget. – Cerin

0

Lea a través de este blog entry y el asociado Django snippet. Espero que esto te dé algunas ideas.

+0

Gracias. El fragmento proporciona más pistas. Pero sigue siendo un trabajo de detective. Estoy buscando cómo usarlo leyendo el código y viendo las muestras. Todavía estoy esperando que alguien que ya ha resuelto este misterio pueda ofrecernos una pequeña guía de cómo consumir. –

Cuestiones relacionadas