2015-07-21 34 views
4

我害怕的另一個基本問題,我正在努力。我已經瀏覽了各種Django文檔頁面,並且還搜索了這個網站。我在這裏找到的唯一一件事是在2013年回來,它建議設置一個自定義過濾器模板。Django窗體來指示輸入類型

無論如何,我試圖生成自己的表單,而不是使用Django自己的方式通過{{form}}生成它。這很簡單,所以我可以控制表單的呈現方式。

我已經制定了各種方式來訪問所需的信息,如(在我的表單循環中的項目);

  • item.help_text
  • item.label_tag
  • item.id_for_label

我試圖找出項目類型,這樣我就可以使用正確的輸入類型,但是我掙扎鍛鍊item.xxxx應該是什麼。由於這是通過{{form}}正確顯示的,我假定這些信息在表單中的某處可用,只是努力找出如何訪問它,以便我可以識別正確的輸入類型。我正在手動執行此操作,因此我可以使用正確的Bootstrap樣式來顯示輸入字段。

任何援助將不勝感激(或只是指向正確的方向)。我對此非常陌生,所以對於我非常基本的問題表示歉意,如果不知道某人,我很難去問這些問題。

問候

韋恩

不知道,如果你需要它,但這裏是一些代碼;

形式:

class NewsForm(ModelForm): 
    class Meta: 
     model = News_Article 
     exclude = ('news_datetime_submitted', 'news_yearmonth',) 
     labels = { 
      'news_title': _('Enter News Title'), 
     } 
     help_texts = { 
      'news_title': _('Enter a title to give a short description of what the news is.'), 
     } 
     error_messages = { 
      'news_title': { 
       'max_length': _("News title is too long."), 
      }, 
     } 

視圖(在POST位沒有奏效呢,這正是從Django文檔的,POST是我的下一個工作了的東西)

def create(request, dataset): 
    if dataset not in ['news', 'announcement']: 
     return HttpResponseRedirect(reverse('pages')) 
    rDict = {} 
    if request.method == 'POST': 
     if dataset == "news": 
      form = NewsForm(request.POST) 
     elif dataset == "announcement": 
      form = AnnouncementForm(request.POST) 
     if form.is_valid(): 
      return HttpResponseRedirect('/home/') 
     else: 
      pass 
    else: 
     announcement = get_announcement() 
     if not announcement == None: 
      rDict['announcement'] = announcement 
     if dataset == "news": 
      rDict['form'] = NewsForm() 
      rDict['branding'] = {'heading': 'Create News Item', 'breadcrumb': 'Create News', 'dataset': 'create/' + dataset + '/'} 
     elif dataset == "announcement": 
      rDict['form'] = AnnouncementForm() 
      rDict['branding'] = {'heading': 'Create Announcement', 'breadcrumb': 'Create Announcement', 'dataset': 'create/' + dataset + '/'} 
     rDict['sitenav'] = clean_url(request.path, ['"', "'"]) 
     rDict['menu'] = Menu.objects.all().order_by('menu_position') 
#  pdb.set_trace() 
     return render(request, 'en/public/admin/admin_create.html', rDict) 

模板代碼

<form action="/siteadmin/{{ branding.dataset }}" method="post"> 
    {% csrf_token %} 
    {% for item in form %} 
     <div class="row"> 
      <div class="col-xs-2 col-md-2"> 
      </div> 
      <div class="col-xs-4 col-md-4"> 
       <div class="panel-title pull-right"> 
        {% if item.help_text %} 
         <img src="/static/images/info.png" height="20" width="20" aria-hidden="true" data-toggle="popover" title="{{ item.help_text }}">&nbsp 
        {% endif %} 
        {{ item.label_tag }} 
       </div> 
      </div> 
      <div class="col-xs-4 col-md-4"> 
       <div class="input-group">  
        <input type="{{ item.widget }}" class="form-control" placeholder="" aria-describedby="{{ item.id_for_label }}"> 
       </div> 
      </div> 
      <div class="col-xs-2 col-md-2"> 
       {% if forloop.last %} 
        <input type="submit" value="Submit" /> 
       {% endif %} 
      </div>   
     </div> 
    {% endfor %} 
</form> 

回答

5

試試這個:

<input type="{{ item.field.widget.input_type }}" ... 

沒有鏈接的文檔,發現它使用調試器(不是最好的做法,我知道...)

按@藍精靈的評論,這不會對所有小工作,像SelectCheckBox,任何MultiWidget,等...似乎只能進行文字輸入和它的變種工作(密碼,電子郵件......)


一個更好的解決方案是創建定製的部件和渲染模板的表單字段照常。您可以設置任何自定義屬性那裏,看到https://docs.djangoproject.com/en/1.8/ref/forms/widgets/#customizing-widget-instances


如果你絕對必須修改控件模板,然後使用django-widget-tweaks

這個應用程序提供了一個非常漂亮的表格過濾器來改變小部件(即其屬性)。但請注意,它是通過字符串與已經呈現的HTML進行交互的方式(「render」表示爲Widget實例)。

+1

,請不要使用這一點 - 這不會出現在所有'Widget'類型。例如,它不會出現在「選擇」小部件上。創建自定義小部件是正確的答案。 – DanielB

+0

再次感謝@frnhr的回覆。有趣的是,CheckBox似乎不起作用。 Item.field.widget會將CheckBox項目列爲 Smurf

+0

謝謝DanielB。注意到那個。如果我使用模型創建表單,您是否有指向創建自定義小部件的howto指南的鏈接?除非我在Django指南中誤解了某些內容,否則在從頭開始創建表單時會通過創建自定義小部件。對於我目前正在進行的項目來說,手動執行它並沒有太大的問題,但是我的下一個項目會有很多表單域。謝謝,韋恩 – Smurf

3

這是做錯的方法。你在這裏做的定製都是輸入的屬性,這些屬性在表單類本身中很簡單。

class NewsForm(ModelForm): 
    news_title = forms.CharField(widget=forms.TextInput(
     attrs={'class': 'form-control', 'placeholder': 'whatever', label: ('Enter News Title')}) 

,現在你可以這樣做:

<div class="input-group">  
    {{ item }} 
</div> 

編輯

如果你不想重新定義每個字段,你可以直接在Meta類設置的部件:

class Meta: 
    model = News_Article 
    widgets = { 
     'news_title': forms.TextInput(attrs={'class': 'form-control'}) 
    } 

如果即使那是太多的重複,你可以mod IFY的屬性直接在窗體的__init__方法:

class NewsForm(ModelForm): 
    def __init__(self, *args, **kwargs) 
     super(NewsForm, self).__init__(*args, **kwargs) 
     for field in self.fields.values(): 
      field.widget.attrs['class'] = 'form-control' 
+0

感謝daniel-roseman的回覆。我確實想過這樣做,但是這不允許你將模型放在模型上,這是我在上面做的。令人沮喪的是,Django沒有提供必要的屬性來手動創建表單更容易(即我找不到檢測輸入類型的方法,所以我可以自定義輸入類型。 – Smurf

+0

我不理解您的評論。這是絕對基於模型的;你唯一要做的就是覆蓋'news_title'字段,你甚至可以通過在Meta類中定義一個'widgets'字典來自定義這個小部件 –

+0

對不起,Daniel,讓自己感到困惑不是,你的課是不是手動爲NewsForm創建表單域?這就是我的回放意思。我有類Meta:model = News_Article,所以我不需要定義每個字段和數據類型。使用已定義的模型時,我不正確嗎? – Smurf