Search code examples
djangodjango-registration

AJAX Form post for Django registration 1.0


I have a view that sub classes from Django registration 1.0:

class RegistrationView(RegistrationView):
    pass

I do this because I would like to now make the post over AJAX. I'm not sure what methods I have to overwrite tho? any examples or advise?

This is my view.py:

{% block content %}
<form method="post" action="" id="registration">

  {{ form.as_p }}

  <input type="submit" value="{% trans 'Submit' %}" />
</form>



 <script>


$('#registration').submit(function(e){
     e.preventDefault(); //prevent default form submit

   $.ajax({

       url: '/accounts/register/',
       type: 'POST',
       contentType: "application/json;charset=utf-8",
       dataType: "json",
       data: {
            'csrfmiddlewaretoken': '{% csrf_token %}',
            'id_username': $("#id_username").val(),
            'id_email': $("#id_email").val()
            },
        success: function() {
            alert('Test');

        },
        error: function(errorThrown){
            console.log(errorThrown);
            alert('Error');
            alert(errorThrown);
        }
    });



});

Django registration 1.0 view

class RegistrationView(_RequestPassingFormView):
    """
    Base class for user registration views.

    """
    disallowed_url = 'registration_disallowed'
    form_class = RegistrationForm
    http_method_names = ['get', 'post', 'head', 'options', 'trace']
    success_url = None
    template_name = 'registration/registration_form.html'

    def dispatch(self, request, *args, **kwargs):
        """
        Check that user signup is allowed before even bothering to
        dispatch or do other processing.

        """
        if not self.registration_allowed(request):
            return redirect(self.disallowed_url)
        return super(RegistrationView, self).dispatch(request, *args, **kwargs)

    def form_valid(self, request, form):
        new_user = self.register(request, **form.cleaned_data)
        success_url = self.get_success_url(request, new_user)

        # success_url may be a simple string, or a tuple providing the
        # full argument set for redirect(). Attempting to unpack it
        # tells us which one it is.
        try:
            to, args, kwargs = success_url
            return redirect(to, *args, **kwargs)
        except ValueError:
            return redirect(success_url)

    def registration_allowed(self, request):
        """
        Override this to enable/disable user registration, either
        globally or on a per-request basis.

        """
        return True

    def register(self, request, **cleaned_data):
        """
        Implement user-registration logic here. Access to both the
        request and the full cleaned_data of the registration form is
        available here.

        """
        raise NotImplementedError

Solution

  • The "registration 1.0" app hasn't really been created to support ajax in the first place, so you have a lot of overriding to do.

    Just to make the registration working you need something like this:

    import json
    from django.http import HttpResponse
    from django.views.generic.edit import CreateView
    from django.contrib.auth.models import User
    
    from registration.views import RegistrationView
    
    
    class AjaxableResponseMixin(object):
        def get_form_kwargs(self):
            kwargs = {'initial': self.get_initial()}
            if self.request.method in ('POST', 'PUT'):
                dict_ = self.request.POST.copy()
                del dict_['csrfmiddlewaretoken']
                kwargs.update({
                    'data': dict_,
                    'files': self.request.FILES,
                })
            return kwargs
    
        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 form_invalid(self, form):
            response = super(AjaxableResponseMixin, self).form_invalid(form)
    
            if self.request.is_ajax():
                return self.render_to_json_response(form.errors, status=400)
            else:
                return response
    
        def form_valid(self, request, form):
            if self.request.is_ajax():
                new_user = self.register(request, **form.cleaned_data)
                data = {
                    'pk': new_user.pk,
                }
                return self.render_to_json_response(data)
            else:
                response = super(AjaxableResponseMixin, self).form_valid(request, form)
                return response
    
    
    class MyRegistrationView(AjaxableResponseMixin, RegistrationView):
        def register(self, request, **cleaned_data):
            del cleaned_data['password2']
            user = User.objects.create_user(data['username'], data['email'], data['password1'])
            return user
    

    urls.py

    (r'^accounts/register/', MyRegistrationView.as_view()),
    (r'^accounts/', include('registration.backends.default.urls')),
    

    html

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    </head>
    <body>
        <form id="registration" action="." method="post">{% csrf_token %}
            {{ form }}
            <input type="submit" name="submit" value="Submit" />
        </form>
        <script type="text/javascript">
            $('#registration').submit(function(e){
                e.preventDefault();
                $.ajax({
                    url: '/accounts/register/',
                    type: 'POST',
                    dataType: "json",
                    beforeSend: function (request) {
                        request.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
                    },
                    data: $('#registration').serialize(),
                    success: function() {
                        console.log('success');
                    },
                    error: function(errorThrown){
                        console.log(errorThrown);
                    }
                });
            });
        </script>
    </body>
    </html>