2010-08-18 12 views
43

Die Dokumentation fehlt etwas in Bezug auf diese Funktion.Wie verwende ich Djangos MultiWidget?

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] 

Ich sehe ich mit einer Liste von anderen Widgets ein „Widgets“ Eigenschaft erstellen müssen, aber nach, dass es ein wenig Sherlock Holmes bekommt.

Würde mir bitte jemand erklären, wie man das Widget MultiWidget benutzt?

+0

Diese Lösung ist ein bisschen wie ein Hack, ist aber mehr mit der Art und Weise, wie wir auf Unterfelder in der Vorlage zugreifen, zu erwarten. http://stackoverflow.com/questions/24866936/render-only-one-part-of-a-multiwidget-in-django – farthVader

Antwort

51

Interessante Frage und ich denke, vielleicht verdient ein wenig mehr Aufmerksamkeit in der Dokumentation.

Hier ist ein Beispiel von 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) 

Was habe ich getan?

  • subclassed django.forms.widgets.MultiWidget
  • einen Konstruktor implementiert, die mehrere widgets.WidgetName Widgets in einem Tupel erzeugt. Das ist wichtig, weil die Superklasse die Existenz dieses Tupels benutzt, um sich um mehrere Dinge zu kümmern.
  • Mein Format ausgegeben Pass-Through, aber die Idee ist, dass Sie eigenen HTML hinzufügen können hier sollten Sie
  • Ich möchte auch decompress implementiert haben, weil Sie zu haben - Sie sollten Werte aus der Datenbank erwarten weitergegeben in einem einzigen value Objekt. decompress bricht dies für die Anzeige im Widget auf. Wie und was Sie hier machen, hängt von Ihnen ab und hängt vom Widget ab.

Dinge, die ich nicht haben, konnte aber haben, außer Kraft gesetzt:

  • render, ist dies tatsächlich verantwortlich für Widgets machen, so müssen Sie auf jeden Fall die Super-Render-Methode aufrufen, wenn Sie diese Unterklasse. Sie können ändern, wie die Objekte unmittelbar vor dem Rendern angezeigt werden, indem Sie diese untergliedern.

Beispiel, django markitup ‚s Methode machen:

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 - Siehe meine Frage here. value_from_datadict zieht den mit diesem Widget verknüpften Wert aus dem Datenverzeichnis aller übermittelten Daten mit diesem Formular. Im Falle eines Multiwidgets, das ein einzelnes Feld repräsentiert, müssen Sie diesen Wert aus Ihren mehreren Sub-Widgets rekonstruieren, so wie die Daten übermittelt wurden.
  • _get_media kann für Sie nützlich sein, wenn Sie Medien mit Djangos Darstellung von Medien abrufen möchten. Die Standardimplementierung zykliert die Widgets, die nach dem Medium fragen; Wenn Sie es ableiten und irgendwelche ausgefallenen Widgets verwenden, müssen Sie den Super aufrufen. Wenn Ihr Widget Medien benötigt, müssen Sie es mit diesem hinzufügen.

Zum Beispiel markitup ‚s django Widget tut dies:

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) 

Auch hier ist ein Tupel von Pfaden an die richtige Stelle zu schaffen, so wie mein Widget ein Tupel von Widgets in der erstellt wurde __init__ Methode.

Ich denke, dass es für wichtige Teile der MultiWidget Klasse abdeckt. Was Sie zu tun versuchen, hängt davon ab, was Sie erstellt haben und welche Widgets Sie verwenden, weshalb ich nicht einfach auf Details eingehen kann. Wenn Sie jedoch die Basisklasse selbst sehen und sich die Kommentare ansehen möchten, werfen Sie einen Blick auf the source.

+1

Definitiv der beste Leitfaden zum Erstellen von Multi-Widget-Formularfeldern, die ich bisher gesehen habe, und ich glaube, ich habe schon einige gesehen! –

+0

Können Sie ein Beispiel für die Verwendung eines Mehrfachwidgets in einem Modell für zwei Felder in diesem Formular angeben? Oder ist Multi-Widget entworfen, um Felder zu teilen, nicht kombinieren? –

+0

Die Methode 'format_output' war veraltet und existiert nicht mehr in der Widget-Klasse. – Cerin

0

Lesen Sie durch diese blog entry und die damit verbundene Django snippet. Hoffe das gibt dir ein paar Ideen.

+0

Danke. Das Snippet bietet weitere Hinweise. Aber es ist immer noch Detektivarbeit. Ich lese, wie man es benutzt, indem ich den Code lese und die Proben sehe. Ich hoffe immer noch, dass jemand, der dieses Mysterium bereits gelöst hat, ein wenig Anleitungen geben kann, damit wir konsumieren können. –