Django表单指示输入类型

时间:2015-07-21 11:53:52

标签: python django forms django-forms

我担心的另一个基本问题是我正在努力解决的问题。我已经浏览了各种Django文档页面并搜索了这个网站。我在这里找到的唯一一件事是在2013年,它建议设置一个自定义过滤器模板。

无论如何,我正在尝试生成自己的表单,而不是使用Django自己的方式通过{{form}}生成它。这很简单,所以我可以控制表单的呈现方式。

我已经找到了各种方法来访问所需的信息,例如(在我的for form for 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>

2 个答案:

答案 0 :(得分:6)

试试这个:

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

没有链接到文档,通过使用调试器找到它(不是最佳实践,我知道......)

根据@ Smurf的评论,这不适用于所有小部件,例如SelectCheckBox,任何MultiWidget等等...似乎仅适用于文本输入及其变体(密码,电子邮件...)

更好的解决方案是创建自定义小部件并像往常一样在模板中呈现表单字段。您可以在那里设置任何自定义属性,请参阅https://docs.djangoproject.com/en/1.8/ref/forms/widgets/#customizing-widget-instances

如果您必须在模板中修改小部件,请使用django-widget-tweaks

这个应用程序提供了一个漂亮的表单过滤器来改变小部件(即他们的属性)。但请注意,它是通过使用已经呈现的HTML进行字符串显示(“渲染”为Widget实例)来实现的。

答案 1 :(得分: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'})
    }

如果重复过多,您可以直接在表格__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'