Search code examples
jqueryajaxdjangoformscsrf

Django: Submitting same form multiple times causes 403 CSRF exception


I have a form which creates a trip. This form is submitted via AJAX, trip created and then, the form inputs are cleared so user can create another item without refreshing the page.

The problem is that after first submit, Django returns:

CSRF verification failed. Request aborted.

I know that problem is that CSRF Token has been chaned but it wasn't reflected in users cookies since the page wasn't refreshed. The only way which comes to my mind is to use csrfexempt.

View

class TripCreationView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
    form_class = TripCreationForm
    template_name = 'trips/add_new_trip.html'
    success_message = _('New trip has been added')
    context_object_name = 'trip_creation_form'

    def post(self, request, *args, **kwargs):
        return super(TripCreationView, self).post(self, request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(TripCreationView, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(TripCreationView, self).get_context_data(**kwargs)
        context['trip_creation_form'] = context['form']
        return context

    def get_initial(self):
        initial = super(TripCreationView, self).get_initial()
        initial.update({k: v for k, v in self.request.GET.iteritems()})
        return initial

    def form_valid(self, form):
        if self.request.is_ajax():
            form.save()
            return JsonResponse({'status':'OK'})

    def get_success_url(self):
        return self.request.POST.get('success_url') or reverse('frontend:homepage')

But I don't know how to make this work. Do you have any ideas?


Solution

  • The CSRF token isn't supposed to change for every request. It's supposed to be stored in a cookie and only changed each time the user logs in, so unless your app is set up such that it reauthenticates the user from scratch every time, that shouldn't be happening.

    Maybe you're just not sending it in the subsequent requests? My blind guess is that when you clear the form on the page, your somehow clearing the token. Log all your requests and responses and see if it's missing.

    If it is in fact changing you can't figure out why, or if there is a reason it needs to stay that way, then I would try having the server's response to the AJAX call include the new token.