Add example of AJAX form submission. #195

Merged
merged 1 commit into from Sep 17, 2012

Conversation

Projects
None yet
3 participants
Member

mjtamlyn commented Jul 9, 2012

Credit goes to @SystemParadox. Originally developed at #DjangoCon Europe
but wasn't tested enough to merge in.

For history, please see https://github.com/pydanny/django/pull/4

@jezdez jezdez and 1 other commented on an outdated diff Jul 10, 2012

docs/topics/class-based-views/generic-editing.txt
+ data = simplejson.dumps(content)
+ response_kwargs = {'content_type': 'application/json'}
+ response_kwargs.update(kwargs)
+ super(JsonResponse, self).__init__(
+ data,
+ **response_kwargs
+ )
+
+ class AjaxableResponseMixin(object):
+ """
+ Mixin to add AJAX support to a form.
+ Must be used with an object-based FormView (e.g. CreateView)
+ """
+ def render_to_response(self, context, **kwargs):
+ if self.request.is_ajax():
+ raise NotImplementedError
@jezdez

jezdez Jul 10, 2012

Owner

I'm not sure if that's technically correct as it will raise a 500. Is there any previous mentioning of what should happen if AJAX access isn't supported?

@mjtamlyn

mjtamlyn Jul 10, 2012

Member

Almost feels like a Method not allowed but I guess it isn't, more of a Bad Request. Problem (as usual) is returning anything other than a 404 or a 500 from deep in a Mixin - throw an error and catch it, somewhere? To be honest, I'm not that bothered about just cutting out this method all together. It would only happen on a get with AJAX, which you're unlikely to write and would be pretty obvious.

@jezdez jezdez commented on an outdated diff Jul 10, 2012

docs/topics/class-based-views/generic-editing.txt
@@ -203,3 +203,54 @@ Note that you'll need to :ref:`decorate this
view<decorating-class-based-views>` using
:func:`~django.contrib.auth.decorators.login_required`, or
alternatively handle unauthorised users in the :meth:`form_valid()`.
+
+AJAX example
+------------
+
+Here is a simple example showing how you might go about implementing a form that
+works for AJAX requests as well as 'normal' form POSTs::
+
+ from django.http import HttpResponse
+ from django.views.generic.edit import CreateView
+ from django.views.generic.detail import SingleObjectTemplateResponseMixin
+ from django.utils import simplejson
+
+ class JsonResponse(HttpResponse):
@jezdez

jezdez Jul 10, 2012

Owner

As long as we don't have an official JsonResponse in the core, I'm very hesitant to document it like that. Instead we should pass in the content_type and dump the content on the spot in the render_to_response class as demonstrated here: https://docs.djangoproject.com/en/dev/topics/class-based-views/#more-than-just-html

Also, don't use django.utils.simplejson but just the json module.

Owner

jezdez commented Jul 10, 2012

I was more thinking like that:

import json
from django.views.generic.edit import CreateView

class AjaxableResponseMixin(object):
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def render_to_response(self, context, **kwargs):
        if self.request.is_ajax():
            context = json.dumps(context)
            kwargs['content_type'] = 'application/json'
        return super(AjaxableResponseMixin, self).render_to_response(context, **kwargs)

    def form_invalid(self, form):
        if self.request.is_ajax():
            return self.render_to_response(form.errors, status=400)
        else:
            return super(AjaxableResponseMixin, self).form_invalid(form)

    def form_valid(self, form):
        if self.request.is_ajax():
            data = {
                'pk': form.instance.pk,
            }
            return self.render_to_response(data)
        else:
            return super(AjaxableResponseMixin, self).form_valid(form)

class AuthorCreate(AjaxableResponseMixin, CreateView):
    model = Author
Member

mjtamlyn commented Jul 10, 2012

I don't think that will work - the super of render_to_response will create a TemplateResponse, what would that do with a context which is a string? Certainly the template_names aren't relevant any more.

Member

mjtamlyn commented Aug 18, 2012

(rebased from master again)

@timgraham timgraham and 1 other commented on an outdated diff Sep 14, 2012

docs/topics/class-based-views/generic-editing.txt
+ from django.views.generic.edit import CreateView
+ from django.views.generic.detail import SingleObjectTemplateResponseMixin
+
+ class AjaxableResponseMixin(object):
+ """
+ Mixin to add AJAX support to a form.
+ Must be used with an object-based FormView (e.g. CreateView)
+ """
+ def render_to_json_response(self, context, **response_kwargs):
+ data = json.dumps(context)
+ response_kwargs['content_type'] = 'application/json'
+ return HttpResponse(data, **response_kwargs)
+
+ def render_to_response(self, context, **kwargs):
+ if self.request.is_ajax():
+ raise NotImplementedError
@timgraham

timgraham Sep 14, 2012

Owner

I agree we should either remove this method entirely or return something like a 501 Not Implemented (HttpResponse("", status=501)), rather than raising an exception which will 500. Otherwise this looks good to me.

@mjtamlyn

mjtamlyn Sep 15, 2012

Member

I agree. It should never get called given the rest of the code so there's not much point in it being there.

@mjtamlyn mjtamlyn Add example of AJAX form submission.
Credit goes to @SystemParadox. Originally developed at #DjangoCon Europe
but wasn't tested enough to merge in.

For history, please see https://github.com/pydanny/django/pull/4
b16f8b5
Member

mjtamlyn commented Sep 17, 2012

Updated as requested

@timgraham timgraham added a commit that referenced this pull request Sep 17, 2012

@timgraham timgraham Merge pull request #195 from pydanny/ajax-docs-example
Added example of AJAX form submission for CBVs.
89e809c

@timgraham timgraham merged commit 89e809c into django:master Sep 17, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment