Jay P.
Jay P.

Reputation: 2590

How to do form handling in Django Generic CBV?

I'm trying to do the same thing below in Django Generic CBV.

Function Based View

def form_handling(request):
    if request.method == "POST":
        form = SimilarStore(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('...')   
    else:
        form = SimilarStore()
    ...

Class Based View

class SimilarStoreCreateView(CreateView):
    model = SimilarStore
    form_class = SimilarStoreForm
    template_name='cms/similarstore_new.html'
    success_url=reverse_lazy('cms:similarstore')

    def form_valid(self, form):
        form = SimilarStoreForm(self.request.POST, self.request.FILES)
        form.save()
        return redirect(self.get_success_url())

    def form_invalid(self, form):
        form = SimilarStoreForm()
    ...

I'm confused about how I can check if request.method is POST or GET in Django Generic CBV. I know Django regular CBV supports get() and post(). However, in Generic views, there's no post(). What should I do to handle POST requests in Django Generic?

Also, my CBV codes throw an error 'SimilarStoreForm' object has no attribute 'cleaned_data'. Why is that?

Upvotes: 1

Views: 589

Answers (3)

Nikita Shupeyko
Nikita Shupeyko

Reputation: 336

Basically, your current setup is all you need. You see, CreateView's post method is effectively its base class'es (BaseCreateView) post method which calls its own base class'es (ProcessFormView) post method, that being

class ProcessFormView(View):
    # ...
    def post(self, request, *args, **kwargs):
        """
        Handles POST requests, instantiating a form instance with the passed
        POST variables and then checked for validity.
        """
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

Therefore, whenever a POST HTTP request gets routed to SimilarStoreCreateView it will finally be dispatched to the aforementioned post method already implementing the desired workflow of yours.

Upvotes: 1

neverwalkaloner
neverwalkaloner

Reputation: 47374

CreateView has post() method it's inherited from ProcessFormView. You can find method source here. As for your question from the source code you may see that form_valid and form_invalid method will be triggered only for POST requests.

You don't need to override form_invalid method since by default it will render invalid form with form's error. And you don't need to override form_valid also, CreateView do redirect automatically after. So you can simple do:

class SimilarStoreCreateView(CreateView):
    model = SimilarStore
    form_class = SimilarStoreForm
    template_name='cms/similarstore_new.html'
    success_url=reverse_lazy('cms:similarstore')

And this will give you same logic as in your function based view.

Upvotes: 2

leelum1
leelum1

Reputation: 1254

CreateViews have a post method as shown below that you can use

def post(self, request, *args, **kwargs):
    self.object = None
    return super().post(request, *args, **kwargs)

Here is a good reference for all the methods and attributes of CBVs

Upvotes: 1

Related Questions