Search code examples
pythondjangodjango-formsdjango-viewsdjango-generic-views

The view ProductCreateView didn't return an HttpResponse object. It returned None instead


How to redirect to another page from def form_valid(self): inside a generic FormView.

I know I should do something like Super(className, self).form_valid(form): but this will never redirect to a dynamic link, but will only go to the success URL

Here is my code :

class ProductCreateView(FormView):
    form_class = ProductCreateForm
    template_name = 'back_office/product_create_form.html'
    success_url = reverse_lazy('product_recipe_wrapper')

    def form_valid(self, form):
        category = Category.objects.get(id=self.kwargs['pk'])
        name = form.cleaned_data['name']
        image = form.cleaned_data['image']
        big_size = form.cleaned_data['big_size']
        mid_size = form.cleaned_data['mid_size']
        small_size = form.cleaned_data['small_size']
        new_product = Product.objects.create(category=category, name=name, image=image)
        big_size_object = ProductSize.objects.create(product=new_product, size=Size.objects.get(id=1),
                                                     sell_price=big_size)
        mid_size_object = ProductSize.objects.create(product=new_product, size=Size.objects.get(id=2),
                                                     sell_price=mid_size)
        small_size_object = ProductSize.objects.create(product=new_product, size=Size.objects.get(id=3),
                                                       sell_price=small_size)
        if small_size_object.sell_price != 0:
            return reverse_lazy('product_small_recipe', args=[small_size_object.id])

    def get_context_data(self, *args, **kwargs):
        context = super(ProductCreateView, self).get_context_data()
        context['category'] = Category.objects.get(id=self.kwargs['pk'])
        return context


Solution

  • The form_valid method needs to return a response. The error message It returned None instead means that the method didn't return anything at all. In the code above, that would happen when small_size_object.sell_price == 0:.

    Next, you can't do return reverse_lazy(...), because the method needs to return a response, not a URL. If you want to redirect, you can use HttpResponseRedirect, for example:

    from django.http import HttpResponseRedirect
    
    class ProductCreateView(FormView):
        ...
    
        def form_valid(self, form):
            ...
            return HttpResponseRedirect(reverse('product_small_recipe', args=[small_size_object.id]))
    

    Note you can use reverse here instead of reverse_lazy because you're inside a method.

    You can simplify the code by using the redirect shortcut.

    from django.shortcuts import redirect
    
    class ProductCreateView(FormView):
        ...
    
        def form_valid(self, form):
            ...
            return redirect('product_small_recipe', small_size_object.id)