I am currently developing a website with a number of questionnaires on it that are in html table format. The questionnaires are supposed to be answered in a in a Likert fashion with radio buttons. For that I'm trying to render a 'radioSelect' widget as a html table instead of its standard list format. I would like it to look like this:
|----------|---------|-----------|---------|----------|
| | 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 |
|----------|---------|-----------|---------|----------|
And I guess that the html code for the rendered form should look somewhat like this:
<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>
I've tried to figure out how to that based on the answers from this threat from 7 years ago. I'm still a beginner though and a lot has changed in Django since then so I was unfortunately not able to make it work.
I also played around with css based on this thread and I tried to use 'as_table' in my html code but I had no success with those either.
From going through all the other threats that seemed relevant to my problem and from reading the documentation I understand that I have to override the default renderer of 'radioSelect' with my own custom renderer in order to replace the list tags with table tags. Based on that assumption I made the following attempt:
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')
views.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)
formtest.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 %}
I was able to work through a number of error messages but I got completely stuck at the following error message:
TypeError: __init__()
got an unexpected keyword argument 'renderer'
I assume that this error refers to the attribute of the widget. I don't understand how to fix this error however, since I thought that the 'renderer' attribute is needed to override the default renderer.
I would greatly appreciate any kind of help with this. If I'm going into the wrong direction, is there a better way to achieve this maybe?
PS: While having consulted StackOverflow many many times this is the first time that I'm asking a question myself. Any feedback on how to improve my question is very welcome!