Standardised JSON response from views

2019-08-17 05:33发布

问题:

When my page POSTs a form to my Django view, the view returns a response with some data but soon I ran into the issue that my views returned data in different formats and different sets of information. I've thought of using JSON as a standard format to return my data.

There are two types of statuses, success and failure. When the POST was successful, it just returns success but when it has failed, it returns a sub group called errors which contains a of fields and that field's error.

Here's a sample failure response:

{"failure": {
    "errors":[
        {"fieldname": "<fieldname>", 
         "fielderror": "<fielderror>"
        },
        {"fieldname": "<fieldname>", 
         "fielderror": "<fielderror>"
        }]
}}

Here's a sample success response:

{"success": {
    "data":[
        {"fieldname": "<fieldname>", 
         "fielddata": "<fielddata>"
        },
        {"fieldname": "<fieldname>", 
         "fielddata": "<fielddata>"
        }]
}}

(The success response has data fields because quite often you like to return some data i.e. key of newly created DB record.)

This is what I've come up with but so many people using Django out there, I'm wondering whether there is a standard way/more robust of doing this or some module to help with this.

Thanks.

回答1:

been there. I wrote the solution my own (since it's simple. I dont know if theres a module out there for this). This is just a json response wrapper

from django.utils import simplejson
from django.http import HttpResponse

class JsonResponse(HttpResponse):
    def __init__(self, data):
        content = simplejson.dumps(data)
        super(JsonResponse, self).__init__(content=content,
                                           mimetype='application/json')

class Success(JsonResponse):
    def __init__(self, something):
        x = something # set your data here
        content = {'success': {'data': x}}
        super(Success, self).__init__(content)


class Failure(JsonResponse):
    def __init__(self, something):
        x = something # set your data
        content = {'failures': {'errors': x}}
        super(Failure, self).__init__(content)

something like that. In my case, I make Success and Failure accept a string and a dictionary for arguments (like Success(data)) to make it even easier

If your structure is quite complex (or youre too lazy too write them manually), write your own wrapper for that complicated structure (so you can create the response with even less typing), and make the Success/Failure accepts that as argument.



回答2:

Do you know how to use Python dicts? If so then there are libraries which convert your Python dict into valid JSON. Django's built-in is for example is simplejson. Here an example:

from django.utils import simplejson

def my_view(request):
   ....
   my_json = simplejson.dumps(my_dict) #dumps a JSON string from a dict
   my_dict_again = simplejson.loads(my_json) #loads a Python dict from a JSON string

   return HttpResponse(json, mimetype="application/json")


回答3:

Well, I don't know how much this will help you out, but Python does have a module json.

>>> import json
>>> json.dumps({'a':'b', 'c':'d'})
'{"a": "b", "c": "d"}'


回答4:

I think the front end is going to make a stronger case for how you should format your data then some "standard", Different client side frameworks expect different things, and adapt to differences from that expectations better or worse than that.

One way I try to make my own life easier is to have the 'shape' of the response always roughly the same, for example, the response will always have a 'status' property, which always has an 'errors' property, and if there were no errors, then the value of result.status.errors is null. If there were errors, it'd be a list of strings explaining what went wrong. even if there were errors, there'd be a 'value' property, which would be either null if the request couldn't be serviced, or the requested resource if it could.