2011-06-25 17 views
9

मुझे ModelChoiceField के विकल्पों में शीर्षक विशेषता जोड़नी है।django में विकल्प टैग में विशेषताओं को जोड़ने के लिए कैसे?

class LocModelForm(forms.ModelForm): 
     def __init__(self,*args,**kwargs): 
      super(LocModelForm,self).__init__(*args,**kwargs) 
      self.fields['icons'] = forms.ModelChoiceField(queryset = Photo.objects.filter(galleries__title_slug = "markers")) 
      self.fields['icons'].widget.attrs['class'] = 'mydds' 


     class Meta: 
      model = Loc 
      widgets = { 
       'icons' : forms.Select(attrs={'id':'mydds'}), 
       } 

     class Media: 
      css = { 
       "all":("/media/css/dd.css",) 
       } 
      js=(
       '/media/js/dd.js', 
       ) 

class LocAdmin(admin.ModelAdmin): 
    form = LocModelForm 

मैं विजेट का चयन करने के लिए किसी भी विशेषता जोड़ सकते हैं, लेकिन मैं विकल्प टैग विशेषताएं जोड़ने का तरीका पता नहीं कैसे: यहाँ है कि के लिए अपने व्यवस्थापक कोड है। कोई उपाय ?

उत्तर

16

सबसे पहले, यदि आप ओवरराइड करने के लिए विजेट, Meta भीतरी वर्ग उपयोग करें यदि आप, प्रपत्र फ़ील्ड्स ओवरराइड उन्हें एक सामान्य (गैर मॉडल) के रूप में की तरह घोषित करने के लिए चाहते हैं, __init__ में खेतों बदलाव न करें।

यदि Select विजेट आप जो चाहते हैं वह नहीं करता है, तो बस अपना खुद का बनाओ। मूल विजेट एक विकल्प के लिए HTML प्रतिनिधित्व प्राप्त करने के लिए render_option विधि का उपयोग करता है - एक सबक्लास बनाएं, इसे ओवरराइड करें, और जो भी आप चाहते हैं उसे जोड़ें।

class MySelect(forms.Select): 
    def render_option(self, selected_choices, option_value, option_label): 
     # look at the original for something to start with 
     return u'<option whatever>...</option>' 

class LocModelForm(forms.ModelForm): 
    icons = forms.ModelChoiceField(
     queryset = Photo.objects.filter(galleries__title_slug = "markers"), 
     widget = MySelect(attrs = {'id': 'mydds'}) 
    ) 

    class Meta: 
     # ... 
     # note that if you override the entire field, you don't have to override 
     # the widget here 
    class Media: 
     # ... 
+3

क्या कोई विशेष कारण है कि '__init__' विधि के बजाय' मेटा 'आंतरिक वर्ग में फ़ील्ड को संशोधित किया जाना चाहिए? और क्या एक ही तर्क एक क्षेत्र के लिए विजेट विशेषताओं को संशोधित/जोड़ने के लिए लागू होगा? – hellsgate

+1

@hellsgate ज्यादातर मामलों में, 'widget.attrs' सेट करने के लिए' __init__' को ओवरराइड नहीं करने का कोई कारण नहीं है। उपयोग-मामलों के बहुमत में, जैसे अन्यथा डिफ़ॉल्ट विजेट पर एचटीएमएल विशेषताओं को संशोधित करना * नहीं * '__init__' ओवरराइड के माध्यम से ऐसा करना DRY का उल्लंघन करता है। दुर्भाग्यवश ओपी के मामले के लिए, उसे एक विजेट विजेट को परिभाषित करना होगा क्योंकि '

+0

इस दृष्टिकोण का उपयोग 'SelectMultiple' विजेट को बढ़ाने के लिए भी किया जा सकता है। बस 'selectMultiple' subclass और इसे कस्टम' MySelect' विजेट पास करें। – NickBraunagel

4

यहां कक्षा मैंने बनाया forms.Select से कि विरासत में है (मुझे प्राप्त करने के लिए Cat Plus Plus करने के लिए धन्यवाद इस के साथ शुरू कर दिया)। प्रारंभिकरण पर, विकल्प_title_field पैरामीटर प्रदान करता है जो दर्शाता है कि <option> शीर्षक विशेषता के लिए कौन सा फ़ील्ड उपयोग करना है।

from django import forms 
from django.utils.html import escape 

class SelectWithTitle(forms.Select): 
    def __init__(self, attrs=None, choices=(), option_title_field=''): 
     self.option_title_field = option_title_field 
     super(SelectWithTitle, self).__init__(attrs, choices) 

    def render_option(self, selected_choices, option_value, option_label, option_title=''): 
     print option_title 
     option_value = forms.util.force_unicode(option_value) 
     if option_value in selected_choices: 
      selected_html = u' selected="selected"' 
      if not self.allow_multiple_selected: 
       # Only allow for a single selection. 
       selected_choices.remove(option_value) 
     else: 
      selected_html = '' 
     return u'<option title="%s" value="%s"%s>%s</option>' % (
      escape(option_title), escape(option_value), selected_html, 
      forms.util.conditional_escape(forms.util.force_unicode(option_label))) 

    def render_options(self, choices, selected_choices): 
      # Normalize to strings. 
      selected_choices = set(forms.util.force_unicode(v) for v in selected_choices) 
      choices = [(c[0], c[1], '') for c in choices] 
      more_choices = [(c[0], c[1]) for c in self.choices] 
      try: 
       option_title_list = [val_list[0] for val_list in self.choices.queryset.values_list(self.option_title_field)] 
       if len(more_choices) > len(option_title_list): 
        option_title_list = [''] + option_title_list # pad for empty label field 
       more_choices = [(c[0], c[1], option_title_list[more_choices.index(c)]) for c in more_choices] 
      except: 
       more_choices = [(c[0], c[1], '') for c in more_choices] # couldn't get title values 
      output = [] 
      for option_value, option_label, option_title in chain(more_choices, choices): 
       if isinstance(option_label, (list, tuple)): 
        output.append(u'<optgroup label="%s">' % escape(forms.util.force_unicode(option_value))) 
        for option in option_label: 
         output.append(self.render_option(selected_choices, *option, **dict(option_title=option_title))) 
        output.append(u'</optgroup>') 
       else: # option_label is just a string 
        output.append(self.render_option(selected_choices, option_value, option_label, option_title)) 
      return u'\n'.join(output) 

class LocModelForm(forms.ModelForm): 
    icons = forms.ModelChoiceField(
     queryset = Photo.objects.filter(galleries__title_slug = "markers"), 
     widget = SelectWithTitle(option_title_field='FIELD_NAME_HERE') 
    ) 
0

मुझे एक ही समस्या थी, जहां मुझे प्रत्येक विकल्प को गतिशील रूप से एक कस्टम विशेषता जोड़ने की आवश्यकता थी। लेकिन Django 2.0 में, एचटीएमएल प्रतिपादन विजेट बेस क्लास में ले जाया गया था, इसलिए render_option संशोधित करना अब काम नहीं करता है।

from django import forms 

class CustomSelect(forms.Select): 
    def __init__(self, *args, **kwargs): 
     self.src = kwargs.pop('src', {}) 
     super().__init__(*args, **kwargs) 

    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None): 
     options = super(CustomSelect, self).create_option(name, value, label, selected, index, subindex=None, attrs=None) 
     for k, v in self.src.items(): 
      options['attrs'][k] = v[options['value']] 
     return options 

class CustomForm(forms.Form): 
    def __init__(self, *args, **kwargs): 
     src = kwargs.pop('src', {}) 
     choices = kwargs.pop('choices',()) 
     super().__init__(*args, **kwargs) 
     if choices: 
      self.fields['custom_field'].widget = CustomSelect(attrs={'class': 'some-class'}, src=src, choices=choices) 

    custom_field = forms.CharField(max_length=100) 

तो विचारों में, {'form': CustomForm(choices=choices, src=src)} के साथ एक संदर्भ प्रस्तुत करना जहां src इस तरह एक शब्दकोश है: {'attr-name': {'option_value': 'attr_value'}} यहाँ समाधान है कि मेरे लिए काम किया है।

संबंधित मुद्दे