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.