代码之家  ›  专栏  ›  技术社区  ›  jono3030

以django radioselect为html表的likert式问卷

  •  0
  • jono3030  · 技术社区  · 8 年前

    我目前正在开发一个网站,上面有许多html表格格式的问卷。问卷应该在 Likert 时尚的单选按钮。为此,我试图将“radioselect”小部件呈现为html表,而不是其标准列表格式。我希望它看起来像这样:

    |----------|---------|-----------|---------|----------|
    |          |  Never  | Sometimes |  Often  |  Always  |
    |----------|---------|-----------|---------|----------|
    | Question | First 0 | Second 0  | Third 0 | Fourth 0 |
    |----------|---------|-----------|---------|----------|
    | Question | First 0 | Second 0  | Third 0 | Fourth 0 |
    |----------|---------|-----------|---------|----------|
    
    ...
    
    |----------|---------|-----------|---------|----------|
    | Question | First 0 | Second 0  | Third 0 | Fourth 0 |
    |----------|---------|-----------|---------|----------|
    

    我想呈现表单的html代码应该看起来像这样:

    <td><label for="id_choice_field_0"><input type="radio" name="choice_field" value="1" id="id_choice_field_0" required />First</label></td>
    <td><label for="id_choice_field_1"><input type="radio" name="choice_field" value="2" id="id_choice_field_1" required />Second</label></td>
    ...
    <td><label for="id_choice_field_n"><input type="radio" name="choice_field" value="n" id="id_choice_field_n" required />n</label></td>
    

    我试着根据 this 七年前的威胁。不过,我还是一个初学者,从那以后,django发生了很多变化,所以很不幸我没能成功。

    我也玩过基于 this 线程和我试图在我的html代码中使用“as_table”,但我也没有成功。

    通过查看与我的问题相关的所有其他威胁,以及阅读文档,我了解到我必须用自己的自定义呈现器覆盖“radioselect”的默认呈现器,以便用表标记替换列表标记。基于这个假设,我做了如下尝试:

    forms.py格式:

    from django import forms
    from django.utils.safestring import mark_safe
    
    class MyCustomRenderer(forms.RadioSelect):
        def render(self):
            return( mark_safe( u''.join( [ u'<td>%s</td>' % force_unicode(w.tag()) for w in self ] )))
    
    CHOICES = (('1', 'First',),('2', 'Second',),('3', 'Third',),('4', 'Fourth',))
    
    class SelectForm(forms.Form):
        choice_field = forms.ChoiceField(widget=forms.RadioSelect(renderer=MyCustomRenderer), choices=CHOICES, label='TEST')
    

    视图.py:

    from django.shortcuts import render, HttpResponse
    from django.views.generic import TemplateView
    from accounts.forms import SelectForm
    
    class HomeView(TemplateView):
        template_name = 'accounts/formtest.html'
    
        def get(self, request):
            form = SelectForm() 
            return render(request, self.template_name, {'form': form})
    
        def post(self, request):
            form = SelectForm(request.POST)
            if form.is_valid():
            text = form.cleaned_data['choice_field']
    
            args = {'form': form, 'text': text}
            return render(request, self.template_name, args)
    

    表单测试.html:

    {% extends 'base.html' %}
    
    {% block body %}
    <h1>Form test</h1>
    
    <form method="post">
        {% csrf_token %}
        <table>
            <thead>
                <tr>
                    <th></th>
                    <th>Never</th>
                    <th>Sometimes</th>
                    <th>Often</th>
                    <th>Always</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    {% for radio in form %}
                    <td class="question_align">Question<td>
                            {{ radio }}
                    {% endfor %}
                </tr>
            </tbody>
        </table>
    
        <button type="submit">Submit</button>
    
    </form>
    
    <br>
    
    <h1>{{ text }}</h1>
    {% endblock %}
    

    我能够处理许多错误消息,但我完全陷入了以下错误消息:

    类型错误: __init__() 得到意外的关键字参数“renderer”

    我假设这个错误是指小部件的属性。但是,我不知道如何修复此错误,因为我认为需要“renderer”属性来覆盖默认的呈现器。

    我非常感谢你的帮助。如果我走错了方向,有没有更好的方法来实现这一点呢?

    注:虽然我咨询过斯塔克弗洛夫很多次,但这是我第一次问自己一个问题。任何关于如何改进我的问题的反馈都是非常欢迎的!

    1 回复  |  直到 8 年前
        1
  •  0
  •   jono3030    8 年前

    我最终在django文档中找到了问题的答案。结果发现,我在问题中详细介绍的方法已经过时,在最近的django版本中不起作用。开发django的团队创建了一个更加优雅和直接的方法:您不必重写forms.py中的呈现程序,而必须在html文件中使用django模板语言。它被描述 here 是的。

    我会更多地玩弄它(如果我发现有重要的事情要补充的话,我会更新我的答案),但据我所知,你必须:

    1)调用表单时按名称指定字段;
    2)手动添加必要的标签;
    3)使用单选按钮的标记属性。

    这是对我有用的代码:

    {% extends 'base.html' %}
    
    {% block body %}
    <h1>Form test</h1>
    
    <form method="post">
        {% csrf_token %}
        <table>
            <thead>
                <tr>
                    <th></th>
                    <th>Never</th>
                    <th>Sometimes</th>
                    <th>Often</th>
                    <th>Always</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td class="question_align">Question<td>
                    {% for radio in form.choice_field %}
                        <td class="question_align">{{ radio.tag }}</td>
                    {% endfor %}
                </tr>
            </tbody>
        </table>
    
        <button type="submit">Submit</button>
    
    </form>
    
    <br>
    
    <h1>{{ text }}</h1>
    {% endblock %}
    

    一旦你知道了就很明显了。

    不管怎样,希望这能帮助别人!