7

I'm trying to figure out the best way to send post data to a Django View function.

What I have currently in my jquery code is something like this:

var name = 'Joe';
var age = 20;

$.ajax({
    url:"/do_something/",
    type: "POST",
    data: {name: name, age: age},
    success:function(response){},
    complete:function(){},
    error:function (xhr, textStatus, thrownError){
        alert("error doing something");
    }
});

The data arrives in Django in a QueryDict object:

<QueryDict: {u'name': [u'Joe'], u'age': [u'20']}>

In the view function, I can access the values like this:

def do_something(request):
    if request.POST:
        name = request.POST.getlist('name')[0]
        age = request.POST.getlist('age')[0]

This feels wrong somehow (accessing the post data through a getlist and then getting the first element in the list) as a way to pass post data from jquery to django. Is there a better way to send data?

Steve Walsh
  • 6,363
  • 12
  • 42
  • 54
  • How do you get the view do_something to get called? I'm doing something similar but when calling the do_something it doesn't reach urls.py. I keep searching. – madtyn Nov 18 '14 at 21:52

3 Answers3

5

This might be the "right way" to do this, though it is not any lighter.

You can read the JSON data from HttpRequest object's POST list using [] notation, for example:

JSONdata = request.POST['data']

and then decode the JSON data:

dict = simplejson.JSONDecoder().decode( JSONdata ) 

and you end up having all your JSON data in the dict variable. Example usage:

username = dict['name']
supertopi
  • 3,469
  • 26
  • 38
4

Why do you need to use getlist at all? Django's QueryDict objects use lists for all items, but a simple get - or even normal dictionary access - always gets the first item. So this:

name = request.POST['name']

works fine.

Also, I don't understand the way you build up the JS object in the first place. What's the point of ""+name? Why not just {name: name, age: age}?

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
3

You can create a form and put the code that saves this data into .save method. This way you also get validation for free. If you do multiple lookups to request.POST and validation in a view, you might have separated the concerns in a wrong way.

If you just want to save this data into a model, use ModelForm class (you can make a form with only some fields of the model).

class PersonForm(forms.Form):
    name = forms.Charfield(max_length=50)
    age = forms.IntegerField(min_value=0, max_value=150)

    def save(self):
        data = self.cleaned_data
        # do what you need here

# protect the view with require_POST decorator
from django.views.decorators.http import require_POST        

@require_POST
def myview(request):
    form = PersonForm(data=request.POST)
    form.save()

Another benefit of a form is that you can render it in a page and, using jquery.form.js plugin, submit it over ajax without pushing any data manually:

$('#personform').ajaxForm({
    success: function one,
    error: function two
})
culebrón
  • 34,265
  • 20
  • 72
  • 110