2009-12-10 12 views
5

Ich benutze Django jeden Tag jetzt für drei Monate und es ist wirklich toll. Schnelle Entwicklung von Webanwendungen.In Django Formular, benutzerdefinierte SelectField und SelectMultipleField

Ich habe immer noch eine Sache, die ich nicht genau so machen kann, wie ich will. Es ist das SelectField und SelectMultiple Feld.

Ich möchte in der Lage sein, einige Argumente zu einer Option eines Select.

ich endlich Erfolg mit dem optgroup:

class EquipmentField(forms.ModelChoiceField): 
    def __init__(self, queryset, **kwargs): 
     super(forms.ModelChoiceField, self).__init__(**kwargs) 
     self.queryset = queryset 
     self.to_field_name=None 

     group = None 
     list = [] 
     self.choices = [] 

     for equipment in queryset: 
      if not group: 
       group = equipment.type 

      if group != equipment.type: 
       self.choices.append((group.name, list)) 
       group = equipment.type 
       list = [] 
      else: 
       list.append((equipment.id, equipment.name)) 

Aber für eine andere Modelform, muß ich die Hintergrundfarbe jeder Option ändern, um die Farbe Eigenschaft des Modells.

Wissen Sie, wie ich das tun kann?

Vielen Dank.

Antwort

5

Was Sie tun müssen, ist die Ausgabe zu ändern, die durch das Widget gesteuert wird. Standard ist das Auswahl-Widget, also können Sie es unterklassifizieren. Es sieht so aus:

class Select(Widget): 
    def __init__(self, attrs=None, choices=()): 
     super(Select, self).__init__(attrs) 
     # choices can be any iterable, but we may need to render this widget 
     # multiple times. Thus, collapse it into a list so it can be consumed 
     # more than once. 
     self.choices = list(choices) 

    def render(self, name, value, attrs=None, choices=()): 
     if value is None: value = '' 
     final_attrs = self.build_attrs(attrs, name=name) 
     output = [u'<select%s>' % flatatt(final_attrs)] 
     options = self.render_options(choices, [value]) 
     if options: 
      output.append(options) 
     output.append('</select>') 
     return mark_safe(u'\n'.join(output)) 

    def render_options(self, choices, selected_choices): 
     def render_option(option_value, option_label): 
      option_value = force_unicode(option_value) 
      selected_html = (option_value in selected_choices) and u' selected="selected"' or '' 
      return u'<option value="%s"%s>%s</option>' % (
       escape(option_value), selected_html, 
       conditional_escape(force_unicode(option_label))) 
     # Normalize to strings. 
     selected_choices = set([force_unicode(v) for v in selected_choices]) 
     output = [] 
     for option_value, option_label in chain(self.choices, choices): 
      if isinstance(option_label, (list, tuple)): 
       output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value))) 
       for option in option_label: 
        output.append(render_option(*option)) 
       output.append(u'</optgroup>') 
      else: 
       output.append(render_option(option_value, option_label)) 
     return u'\n'.join(output) 

Es ist eine Menge Code. Aber was Sie tun müssen, ist ein eigenes Widget mit einer veränderten Rendermethode zu erstellen. Es ist die Rendermethode, die den HTML-Code bestimmt, der erstellt wird. In diesem Fall müssen Sie die Methode render_options ändern. Hier könnten Sie eine Überprüfung einschließen, um zu bestimmen, wann eine Klasse hinzugefügt werden soll, die Sie stylen können.

Eine andere Sache, in Ihrem Code oben sieht es nicht so aus, als ob Sie die letzte Gruppenauswahl anhängen. Möglicherweise möchten Sie auch einen order_by() zum Abfrage-Set hinzufügen, da Sie ihn nach dem Typ sortieren müssen. Sie könnten dies in der init-Methode tun, so dass Sie nicht alles bei der Verwendung des Formularfelds erledigen müssen.

+0

Ok, also sollte ich ein komplettes SelectWidget erstellen. Ich werde es versuchen, danke. – Natim

0

Sie sollten sich nicht mit Formularfeldern anlegen, um dem gerenderten HTML-Tag einige benutzerdefinierte Attribute hinzuzufügen. Aber Sie sollten subclass und fügen Sie diese zum Widget hinzu.

Vom docs: customizing-widget-instances

Sie können attrs Wörterbuch der Form Widgets, die als Attribute auf die Ausgabeform Widgets machen einreichen.

class CommentForm(forms.Form): 
    name = forms.CharField(
       widget=forms.TextInput(attrs={'class':'special'})) 
    url = forms.URLField() 
    comment = forms.CharField(
       widget=forms.TextInput(attrs={'size':'40'})) 
Django will then include the extra attributes in the rendered output: 

>>> f = CommentForm(auto_id=False) 
>>> f.as_table() 
<tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> 
<tr><th>Url:</th><td><input type="text" name="url"/></td></tr> 
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> 
+0

Dies ist für den allgemeinen Bereich. Und das mache ich schon, aber wie machst du das als Option für ein SelectWidget? – Natim