0

I want to be able to submit reviews for teachers. I have 2 models:

models.py

class Teacher(models.Model):
    user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='Teacher')

class Review(models.Model):
    teacher = models.ForeignKey(Teacher)
    #other fields

    def __str__(self):
        return self.name

forms.py

class ReviewForm(forms.ModelForm):
    class Meta:
        model = Review
        #Note no 'teacher' in fields below
        fields = ('title','star','body')

views.py I have the following form handling:

def teacher_view(request,**kwargs):
    teacher = Teacher.objects.get(pk=kwargs['pk'])
    #if request.method == 'POST':
    #handle the form
    review_form = ReviewForm(request.POST, instance=teacher)
    review_form.teacher=teacher
    if review_form.is_valid():
         review_form.save()
         return redirect('users:index')
    else:

For some reason, I also seem to get the else loop. E.g. the form is not valid.

Urls.py

url(r'^(?P<pk>[0-9]+)/$', views.teacher_view, name='detail')

Full Views.py

def teacher_profile(request, **kwargs):
    teacher = Teacher.objects.get(pk=kwargs['pk'])
    reviews = Review.objects.filter(teacher_id=kwargs['pk'])
    star = Review.objects.filter(teacher_id=kwargs['pk']).aggregate(Avg('star'))
    no_of_ratings = Review.objects.filter(teacher_id=kwargs['pk']).count()

    if request.method == "POST":
        if 'booking' in request.POST:
            form = BookingForm(request.POST)
            if form.is_valid():
                #handle the form
                return redirect('users:index')
            else:
                review_form = ReviewForm()
        elif 'review' in request.POST:
            review_form = ReviewForm(request.POST)
            review_form['teacher']=teacher
            if review_form.is_valid():
                review_form.save()
                return redirect('users:index')
            else:
                form = BookingForm()
        else:
            form = BookingForm()
            review_form = ReviewForm()
    else:
        form = BookingForm()
        review_form = ReviewForm()

    return render(request, "users/teacher_detail.html", context={"form": form,
                                                                 "review_form":review_form,
                                                                 "teacher":teacher,
                                                                 "reviews":reviews,
                                                                 "star":star,
                                                                 "no_of_ratings":no_of_ratings,
                                                                 })

I've added the code again. I've copy pasted it from my views.py, but removed the form handling where I just define variables and redirect to another page with a success message.

I think why the logic in your answer is wrong, because it first checks if form is valid, which is not valid because teacher is missing. And then we define the teacher, after checking if it was valid. I tried manipulating the code by adding review_form['teacher']=teacher before form.is_valid(), but always get the error:

'ReviewForm' object does not support item assignment

2
  • 1
    in your ReviewForm you use model = Review but in the initial data you provide the instance of the Teacher model Commented Sep 16, 2017 at 21:14
  • Do you mean the instance=teacher part? Even if it's not there, I still get invalid form Commented Sep 16, 2017 at 21:19

1 Answer 1

1

Looks like you want to add teacher if ReviewForm is valid:

def teacher_profile(request,**kwargs):
    teacher = Teacher.objects.get(pk=kwargs['pk'])
    reviews = teacher.review_set.all()
    star = reviews.aggregate(Avg('star'))
    no_of_ratings = reviews.count()

    form = BookingForm()
    review_form = ReviewForm()

    if request.method == "POST":
        if 'booking' in request.POST:
            form = BookingForm(request.POST)
            if form.is_valid():
                #Correct handling
                return redirect('users:index')
        elif 'review' in request.POST:
            review_form = ReviewForm(request.POST)
            if review_form.is_valid():
                review = review_form.save(commit=False)
                review.teacher = teacher
                review.save()
                return redirect('users:index')
    context = {
       "form":form,
       "review_form":review_form,
       "teacher":teacher,
       "reviews":reviews,
       "star":star,
       "no_of_ratings":no_of_ratings,})
    return render(request, "users/teacher_detail.html", context)

in the teacher_detail.html add,

{{ review_form.errors }}
Sign up to request clarification or add additional context in comments.

13 Comments

Thanks, but it still doesn't redirect or create a review. I posted the full content of my view function
try to look on your form errors in the console by add print after else
When I tried doing that, the function print is highlighted in grey, and is no errors are printed when I submit the form.
after putting {{ review_form.errors }} in my template, I get the error: teacher This field is required. So I'm assuming teacher is not assigned to the form properly
you show wrong (not working) code in your full view.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.