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?

43
demandé sur Manoj Govindan 2010-08-18 16:07:49

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 objet value . 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 .

51
répondu Community 2017-05-23 11:47:22

lire à travers cette entrée de blog et le Django associé snippet . Espérons que cela vous donne quelques idées.

0
répondu Manoj Govindan 2010-08-18 12:18:27