2009-12-10 14 views
5

Attualmente sto usando Django ogni giorno per tre mesi ed è davvero fantastico. Veloce sviluppo di applicazioni web.Nel formato Django, personalizzato SelectField e SelectMultipleField

Ho ancora una cosa che non posso fare esattamente come voglio. È il campo Seleziona campo e Seleziona più.

Voglio essere in grado di mettere alcuni args su un'opzione di Select.

ho finalmente successo con l'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)) 

Ma per un altro ModelForm, devo cambiare il colore di ogni opzione di fondo, utilizzando la proprietà colore del modello.

Sai come posso farlo?

Grazie.

risposta

5

Quello che devi fare è cambiare l'uscita controllata dal widget. L'impostazione predefinita è il widget di selezione, quindi puoi creare una sottoclasse. Assomiglia a questo:

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) 

È un sacco di codice. Ma quello che devi fare è creare il tuo widget con un metodo di rendering modificato. È il metodo di rendering che determina l'html che viene creato. In questo caso, è il metodo render_options che devi modificare. Qui puoi includere alcuni controlli per determinare quando aggiungere una classe, che potresti modellare.

Un'altra cosa, nel tuo codice sopra non sembra aggiungere le ultime scelte di gruppo. Inoltre, è possibile aggiungere un order_by() al queryset, in quanto è necessario ordinarlo in base al tipo. Puoi farlo nel metodo init, quindi non devi farlo dappertutto quando usi il campo modulo.

+0

Ok, quindi dovrei creare un SelectWidget completo. Lo proverò, grazie. – Natim

0

Non si deve scherzare con i campi modulo per aggiungere alcuni attributi personalizzati al tag html renderizzato. Ma dovresti creare una sottoclasse e aggiungerne una al Widget.

Dal docs: customizing-widget-instances

Puoi inviare attrs dizionario per i widget, che rendono come attributi i widget del form di uscita.

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

Questo è per il campo comune. E lo faccio già, ma come lo fai per l'opzione di SelectWidget? – Natim