2015-07-21 52 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