1👍
To create forms for models which have a OneToMany relation I would recommend you to use Django’s inline formsets: https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#inline-formsets
It’s a really simple and elegant way to create forms for related models.
To parse the choices, the user entered you could just override the clean
method of your form. In this the user content is usually checked and prepared for storing it to the database. https://docs.djangoproject.com/en/1.8/ref/forms/validation/#form-field-default-cleaning
So cleaning could look like this:
class QuestionForm(ModelForm):
...
def clean(self):
cleaned_data = super(QuestionForm, self).clean()
if cleaned_data['choice_name'].startswith('Something'):
raise forms.ValidationError(
"Choice names cannot start with 'Something'!"
)
1👍
You models seems to be correct, in order to be able to add mutiple choices in your template you need a formset. In addition you can put a formset and a form inside the same html form in a template and have them be validated individually. Each one only cares about the POST data relevant to them. Something like:
template.html
<form method="post" action="">
{% csrf_token %}
{{ choices_formset.management_form }} <!-- used by django to manage formsets -->
{{ question_form.as_p }}
{% for form in choices_formset %}
{{ form.as_p }}
{% endfor %}
<button type='submit'>Submit</button>
</form>
views.py
from django.db import IntegrityError, transaction
from django.shortcuts import redirect
from django.forms.formsets import formset_factory
from django.core.urlresolvers import reverse
def new_question(request):
ChoicesFormset = formset_factory(ChoicesForm)
if request.method == 'POST':
question_form = QuestionForm(request.POST)
choices_formset = ChoicesFormset(request.POST)
if question_form.is_valid():
question = Question(**question_form.cleaned_data)
if choices_formset.is_valid():
question.save()
new_choice_list = list()
append_choice = new_choice_list.append
for form in choices_formset:
form.cleaned_data.update({'question': question})
append_choice(Choice(**form.cleaned_data))
try:
with transaction.atomic():
Choice.objects.bulk_create(new_choice_list)
except IntegrityError as e:
raise IntegrityError
return redirect(reverse('question-detail-view', kwargs={'id': question.id}))
def question_detail(request, id):
question_list = Question.objects.get(id=id)
return render(request, 'question_detail.html', {'question_list': question_list})
urls.py
url(r'^question/$', new_question, name='new-question-view'),
url(r'^question/(?P<id>\d+)/$', question_detail, name='question-detail-view'),
If you want to use rather Ajax submission rather than django form sumbission check this tutoriel.
- [Answered ]-How can I model this behavior in Django?
- [Answered ]-How to create an instance of an object in session using django?
- [Answered ]-Django – change site_header when using `admin/login.html` template as a normal login template