2014-09-04 74 views
3

說我有以下型號...增加額外的數據,以小組件輸出爲外鍵字段

class Person(models.Model): 
    name = models.CharField() 
    specialty = models.CharField() 

class Team(models.Model): 
    captain = models.ForeignKey(Person) 
    vice_captain = models.ForeignKey(Person) 

,我有創造一個團隊的形式...

class TeamForm(ModelForm): 
    class Meta: 
      model = Team 
      widgets['vice_captain'] = MySelectWidget() 

我也有該表格還有一個額外的限制,即副隊長必須具有與隊長相同的特長。我已經以乾淨的形式實施了檢查,但希望UI自己「過濾」。我已經決定,而不是使用ajax填充/過濾字段,我會將html數據標籤添加到窗口小部件輸出中,然後用javascript隱藏選項。

我已經寫了一個小部件(和JavaScript),與選擇小部件一起使用。在這裏(注意這是從我的實際代碼簡化,但應該工作)。

class Select_with_Data(forms.Select): 
    # Not sure if this is necessary. 
    allow_multiple_selected = False 

    def render_option(self, selected_choices, option_value, option_label): 

     # This paragraph is copied from django Select. 
     option_value = force_text(option_value) 
     if option_value in selected_choices: 
      selected_html = mark_safe(' selected="selected"') 
      if not self.allow_multiple_selected: 
       # Only allow for a single selection. 
       selected_choices.remove(option_value) 
     else: 
      selected_html = '' 

     # My custom code to add data-specialty attributes to <option> tags. 
     # Get the object to filter upon. 
     obj = self.choices.queryset.get(pk=option_value) 
     # Get the data field. 
     data_field = getattr(obj, 'specialty', False) 
     # If the data field has a value set, add it to the return html. 
     # Need to check if the data_field has a pk (ie is a ForeignKey field), and handle it appropriately. 
     if data_field: 
      selected_html += ' data-{0}={1}'.format('specialty', str(getattr(data_field, 'pk', data_field))) 

     # This paragraph is copied from django Select. 
     return format_html('<option value="{0}" {1}>{2}</option>', 
          option_value, 
          selected_html, 
          force_text(option_label)) 

但現在我已經決定我想單選按鈕,而不是選擇列表。我的問題是,試圖在無線電裝置的渲染器中使用與上面類似的代碼失敗,因爲self.choices.queryset沒有設置,所以我無法訪問我需要的信息。 我怎樣才能獲得我需要的信息,這是做我想做的最好的方式?

我甚至修改了核心django文件,以查看查詢集消失的位置。 RadioSelect的子類RendererMixin。 self.choices.queryset在其init,render和get_renderer?子函數期間可用。 (是功能的話?)。 RadioSelect的渲染器是RadioFieldRenderer,它是ChoiceFieldRenderer的子類。在其初始化和呈現雖然,查詢集已經消失(它設置自己的self.choices,但即使在初始,self.choices沒有設置此步驟)。

回答

3

我發現了幾種不同的方法來實現我想要的。

1:編寫一個自定義窗口小部件的子類forms.Widget。這可以完全控制,不會嘗試與核心類一起工作。我使用這個鏈接獲取靈感,https://djangosnippets.org/snippets/2589/

2:修改選擇元組,例如(value,label),並將其更改爲(value,label,object)(例如)。下面的鏈接給出了這樣做的代碼:http://srcmvn.com/blog/2013/01/15/django-advanced-model-choice-field/