unable to save data using django formsets

删除回忆录丶 提交于 2020-03-04 20:51:01

问题


The data entered in the form is not saving in the database and it is not showing any errors. Iam trying to create an exam with atleast one question, using ExamModelForm and QuestionFormset. After entering exam details and questions in create_exam_with_questions.html, the create button is not saving the data into the database

views.py

from django.shortcuts import render
from django.shortcuts import redirect
from django.http import HttpResponseRedirect, HttpResponse

from .forms import ExamModelForm, ExamFormset, QuestionFormset
from .models import Question

def create_exam_with_questions(request):
    template_name = 'school/create_exam_with_questions.html'
    if request.method == 'GET':
        examform = ExamModelForm(request.GET or None)
        formset = QuestionFormset(queryset=Question.objects.none())
    elif request.method == 'POST':
        examform = ExamModelForm(request.POST)
        formset = QuestionFormset(request.POST)
        if examform.is_valid() and formset.is_valid():
            # first save this exam, as its reference will be used in `Question`
            exam = examform.save()
            for form in formset:
                # so that `question` instance can be attached.
                question = form.save(commit=False)
                question.exam = exam 
                question.save()
            return redirect("map:map-home")
    return render(request, template_name, {
        'examform': examform,
        'formset': formset,
    })


forms.py

from django import forms
from django.forms import (formset_factory, modelformset_factory)
from .models import Exam, Question

class ExamModelForm(forms.ModelForm):
    class Meta:
        model = Exam
        fields = ['name', 'section', 'duration', 'subject', 'start', 'teacher']

QuestionFormset = modelformset_factory(
    Question,
    fields=('question', 'ans', 'op2', 'op3', 'op4', ),
    extra=1,
    widgets={'question': forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Enter Question here'
        }),
    'ans': forms.TextInput(attrs={
        'class': 'form-control',
        'placeholder': 'Enter answer here'
        }),
    'op2': forms.TextInput(attrs={
        'class': 'form-control',
        'placeholder': 'Enter option2 here'
        }),
    'op3': forms.TextInput(attrs={
        'class': 'form-control',
        'placeholder': 'Enter option3 here'
        }),
    'op4': forms.TextInput(attrs={
        'class': 'form-control',
        'placeholder': 'Enter option4 here'
        }),
    }
)


models.py

class Section(models.Model):
    name = models.CharField(max_length = 20)
    school = models.ForeignKey(School, on_delete = models.CASCADE)

    def __str__(self):
        return self.name

class Subject(models.Model):
    name = models.CharField(max_length = 20)
    section = models.ForeignKey(Section, on_delete = models.CASCADE)

    def __str__(self):
        return self.name


class Exam(models.Model):
    name = models.CharField(max_length = 20)
    section = models.ForeignKey(Section, on_delete = models.CASCADE)
    subject = models.ForeignKey(Subject, on_delete = models.CASCADE)
    duration = models.TimeField()
    start = models.DateTimeField()
    teacher = models.CharField(max_length = 20)

    def __str__(self):
        return self.name


class Question(models.Model):
    question = models.TextField(max_length = 20)
    ans = models.CharField(max_length = 20)
    op2 = models.CharField(max_length = 20)
    op3 = models.CharField(max_length = 20)
    op4 = models.CharField(max_length = 20)
    exam = models.ForeignKey(Exam, on_delete = models.CASCADE)

    def __str__(self):
        return self.question


create_exam_with_questions.html

{% extends "school/base.html" %}

{% block container %}
{% if heading %}
<h3>{{heading}}</h3>
{% endif %}
<form class="form-horizontal" method="POST" action="">
    {% csrf_token %}
<div class="row spacer">
<div class="col-2">
    <label>{{examform.name.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.name}}
    </div>
</div>
</div>
<div class="row spacer">
<div class="col-2">
    <label>{{examform.subject.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.subject}}
    </div>
</div>
</div>
<div class="row spacer">
<div class="col-2">
    <label>{{examform.duration.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.duration}}
    </div>
</div>
</div>
<div class="row spacer">
<div class="col-2">
    <label>{{examform.teacher.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.teacher}}
    </div>
</div>
</div>
<div class="row spacer">
<div class="col-2">
    <label>{{examform.start.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.start}}
    </div>
</div>
</div>
<div class="row spacer">
<div class="col-2">
    <label>{{examform.section.label}}</label>
</div>
<div class="col-4">
    <div class="input-group">
        {{examform.section}}
    </div>
</div>
</div>
{{ formset.management_form }}
{% for form in formset %}
<div class="row form-row spacer">
    <div class="col-2">
        <label>{{form.question.label}}</label>
    </div>
    <div class="col-4">
        <div class="input-group">
            {{form.question}}
        </div>
        <div class="input-group">
            {{form.ans}}
        </div>
        <div class="input-group">
            {{form.op2}}
        </div>
        <div class="input-group">
            {{form.op3}}
        </div>
        <div class="input-group">
            {{form.op4}}
        </div>
    </div>
    <div class="input-group-append">
                <button class="btn btn-success add-form-row">+</button>
    </div>
</div>
{% endfor %}
<div class="row spacer">
    <div class="col-4 offset-2">
        <button type="submit" class="btn btn-block btn-primary">Create</button>
    </div>
</div>
</form>
{% endblock %}

{% block custom_js %}
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script type="text/javascript">
function updateElementIndex(el, prefix, ndx) {
    var id_regex = new RegExp('(' + prefix + '-\\d+)');
    var replacement = prefix + '-' + ndx;
    if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
    if (el.id) el.id = el.id.replace(id_regex, replacement);
    if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function cloneMore(selector, prefix) {
    var newElement = $(selector).clone(true);
    var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
    newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function() {
        var name = $(this).attr('name')
        if(name) {
            name = name.replace('-' + (total-1) + '-', '-' + total + '-');
            var id = 'id_' + name;
            $(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
        }
    });
    newElement.find('label').each(function() {
        var forValue = $(this).attr('for');
        if (forValue) {
          forValue = forValue.replace('-' + (total-1) + '-', '-' + total + '-');
          $(this).attr({'for': forValue});
        }
    });
    total++;
    $('#id_' + prefix + '-TOTAL_FORMS').val(total);
    $(selector).after(newElement);
    var conditionRow = $('.form-row:not(:last)');
    conditionRow.find('.btn.add-form-row')
    .removeClass('btn-success').addClass('btn-danger')
    .removeClass('add-form-row').addClass('remove-form-row')
    .html('-');
    return false;
}
function deleteForm(prefix, btn) {
    var total = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
    if (total > 1){
        btn.closest('.form-row').remove();
        var forms = $('.form-row');
        $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
        for (var i=0, formCount=forms.length; i<formCount; i++) {
            $(forms.get(i)).find(':input').each(function() {
                updateElementIndex(this, prefix, i);
            });
        }
    }
    return false;
}
$(document).on('click', '.add-form-row', function(e){
    e.preventDefault();
    cloneMore('.form-row:last', 'form');
    return false;
});
$(document).on('click', '.remove-form-row', function(e){
    e.preventDefault();
    deleteForm('form', $(this));
    return false;
});

</script>
{% endblock %}


回答1:


You need to replace line

exam = examform.save()

with

examform.save()

and when saving the question, write

for form in formset:
    # so that `question` instance can be attached.
    question = form.save(commit=False)
    question.exam = examform
    question.save()


来源:https://stackoverflow.com/questions/60505144/unable-to-save-data-using-django-formsets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!