How to get instance of a modelform from request.POST ?

One simple way to get an instance of a model is to get the id.

question_1 = Question.objects.get(id=1)

Then you can assign it in another model that has the Question’s key like this.

choice.question = question_1

I am trying to get an instance of another model from a form. In that model, I want to get the value from the template like the below.

selected_teacher = TeacherForm( request.POST )

Then assign it like this one;

choice.teacher = selected_teacher

This gives me the error below

Cannot assign “”: “Student_Answer.teacher” must be a “Teacher” instance.

That’s because TeacherForm appears to be a Form and not an instance of a model.

I suggest you review the Creating Forms from Models page, particularly the sections on Validation on a Model Form and The save() method.

1 Like
question1 = Question.objects.get(id=1)
    question2 = Question.objects.get(id=2)
if request.method == "POST":
        teacher_form = TeacherForm(request.POST)
        form = AnswerForm(request.POST, prefix='question1')
        form1 = AnswerForm(request.POST, prefix='question2')

if (form.is_valid and form1.is_valid() and teacher_form.is_valid()):
            teacher_form.save()
            choice = form.save(commit=False)
            choice.question = question1
            choice.teacher = teacher_form.instance
            choice.save()
            choice = form1.save(commit=False)
            choice.question = question2
            choice.teacher = teacher_form.instance
            choice.save()
return HttpResponseRedirect('/submit/')
else:
        teacher_form = TeacherForm()
        form = AnswerForm(prefix='question1')
        form1 = AnswerForm(prefix='question2')

when I click on submit button, it gets the id of selected item(teacher) and create another model for example, in my teacher model I have [‘bob’, ‘john’] and when I select bob and submitted I have [‘bob’, ‘john’, ‘1’].

I think we’ll need to see the complete view - this excerpt leaves me with a number of questions. (As posted, that code fragment is syntactically invalid)

When you’re posting code, please enclose the code between lines consisting of only three backtick - ` characters. This means you’ll have a line of only ```, followed by your code, followed by another line of ```. This maintains the proper formatting of the code making it easier to read.

Okay here is the complete view.

def index(request):
    all_questions = Question.objects.all()
    question1 = Question.objects.get(id=1)
    question2 = Question.objects.get(id=2)

    if request.method == "POST":
        teacher_form = TeacherForm(request.POST)
        form = AnswerForm(request.POST, prefix='question1')
        form1 = AnswerForm(request.POST, prefix='question2')

        if (form.is_valid and form1.is_valid()):
            teacher_form.save()
            choice = form.save(commit=False)
            choice.question = question1
            choice.teacher = teacher_form.instance
            choice.save()

            choice = form1.save(commit=False)
            choice.question = question2
            choice.teacher = teacher_form.instance
            choice.save()
            return HttpResponseRedirect('/submit/')

    else:
        teacher_form = TeacherForm()
        form = AnswerForm(prefix='question1')
        form1 = AnswerForm(prefix='question2')
    context = {
        'teacher_form': teacher_form,
        'form': form,
        'form1': form1,
        'all_questions': all_questions

    }

    return render(request, 'index.html', context)

Ok, so this looks like this should work. What is the problem you’re having now?

This is the normal Teacher class objects in Admin.

And when I submit the form here is the output in Admin.

4 is the id of the selected teacher. And it also stored in Answer class.

I selected Bob for example, and I have a new object in Teacher class as the id of the selected option in the template. That object also stores in Answer class which is not the result that I want.

Ok, to figure out where this data is coming from, we’ll need to see the model definitions (teacher and questions), the forms TeacherForm and AnswerForm, and your index.html template.

models.py

RATING_CHOICES = ((1, "Weak"), (2, "Average"), (3, "Good"), (4, "Excellent"))

class Question(models.Model):
    question = models.CharField(max_length=200)
    def __str__(self):
        return self.question

class Teacher(models.Model):
    name = models.CharField(max_length=200)
    def __str__(self):
        return self.name

class Student_Answer(models.Model):  
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
    answer = models.SmallIntegerField(choices=RATING_CHOICES, default=1)

forms.py

class AnswerForm(ModelForm):
    class Meta:
        model = Student_Answer
        fields = ('answer',)
        widgets = { 'answer': RadioSelect(choices=RATING_CHOICES),}

class TeacherForm(ModelForm):
    class Meta:
        CHOICES = Teacher.objects.all()
        model = Teacher
        fields = ('name',)
        widgets = {'name': Select(choices=( (x.id, x.name) for x in CHOICES ))}

index.html

{% csrf_token %}
{{ teacher_form}}
{{ all_questions.0}}
{{ form }}
{{ all_questions.1}}
{{ form1 }}

So this appears to be the issue. When you supply a 2-tuple as the choices of a select field, the first element is the value being returned for that field, the second is displayed in the form.