Pass json and deserialize form in django

2019-04-10 13:23发布

问题:

The issue is next: I send some post data with ajax to server. This data looks like:

data = {
  form : $(this).serialize(),
  some_array: [2,3,4,1]
}

How to get form object in django? request.POST['form'] returns a string with a form. I'm trying to use import json library.

But, when I run value = json.load(request.POST['some_array']) or form = json.load(request.POST['form']) it doesn't work.

Printing request.POST['form'] returns the following:

u'csrfmiddlewaretoken=I3LWAjfhZRGyd5NS3m9XcJkfklxNhxOR& address_city=%D0%9A%D0%B8%D1%97%D0%B2& address_street=2& address_building=3& delivery_time=2015-05-15'

回答1:

The form data is not encoded in JSON but as a query string. You can use urlparse.parse_qs from the standard library to parse that query string.

Example:

from urlparse import parse_qs


form_data = parse_qs(request.POST['form'].encode('ASCII'))  # Query strings use only ASCII code points so it is safe.

# To access address_city:
address_city = form_data['address_city'][0].decode('utf-8')

# If you plan to pass form_data to a Django Form,
# use QueryDict instead of parse_qs:
from django.http import QueryDict


form_data = QueryDict(request.POST['form'].encode('ASCII'))


回答2:

Solution 1

Alternatively to aumo 's answer, and assuming you are using jQuery, you may actually want to use .serializeArray() instead of .serialize(), to generate a JSON object that you can then JSON.stringify and POST.

data = {
  form : $(this).serializeArray(),
  some_array: [2,3,4,1]
};

$.ajax(url, {
  data: JSON.stringify(data),
  contentType: 'application/json',
  type: 'POST',
});

As you've pointed out in comments, the format of serializeArray JSON output is not easily usable by a Django form, and requires further processing, after deserializing the content through json.load.

data = json.load(request)
value = data['some_array']

form_data = {}
for f in data['form']:
    if f not in form_data:
        form_data[f['name']] = f['value']
    elif not isinstance(form_data[f['name']], list):
        form_data[f['name']] = [form_data[f['name']], f['value']]
    else:
        form_data[f['name']].append(f['value'])

form = MyForm(data=form_data)

Solution 2

After taking another look at the code, it might be better (and more generic for future safeness) to serialize the form data to proper json format in the frontend.

Although there are many solutions to this; my best bet would be to go with a tried/popular library such as jquery-serialize-object, the code change would be small:

<script src="jquery.serialize-object.min.js"></script>
<script>
    data = {
      form : $(this).serializeObject(),
      some_array: [2,3,4,1]
    };

    $.ajax(url, {
      data : JSON.stringify(data),
      contentType : 'application/json',
      type : 'POST',
    });
</script>

And then the server code would be much simpler

data = json.load(request)
value = data['some_array']
form = MyForm(data=data['form'])