Serialization operation of Django

Keywords: JSON Django Python Javascript

Written in front

Recently, I was trying to drum up wechat applets. I wanted to use Django as the back end to display data in wechat applets. When I write Django, I usually directly throw the QuerySet object to the template and then render it. But in the wechat applet, this object cannot be accepted. You have to write an API to return a Json data format.

Consult and understand

From wiki

JSON (JavaScript Object Notation, read as / ˈ d ʒ e ɪ s ə n /) is a lightweight data exchange language conceived and designed by Douglas Crockford, which is based on easy to read text and is used to transfer data objects composed of attribute values or sequential values. Although JSON is a subset of JavaScript, it is language independent text format and adopts some habits similar to the C language family.
The json data format is language independent. Even though it comes from JavaScript, many programming languages currently support the generation and parsing of json formatted data. The official MIME type of json is application/json, and the file extension is. json

So the question naturally becomes: how to convert objects in Django into json objects to return. Fortunately, Django provides a Serializing Django objects -- serializing objects. Then use the JHttpResponse() method to return json data.

From Django document

Django's serialization framework provides a mechanism for "translating" Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it's possible for a serializer to handle any format (text-based or not).

The general meaning is as follows:

Django's serialization framework provides a mechanism to "translate" Django models into other formats. Typically, these other formats will be text-based and used to send Django data over the network, but the serializer can handle any format (whether text-based or not)

Serialized data

In Django, serializing data is simple:

from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all(),ensure_ascii=False,fields=('desc','title'))

The ensure ABCD parameter defaults to False. This is because RFC requires UTF-8, UTF-16 or UTF-32 to represent JSON,
UTF-8 is recommended as the default for maximum interoperability. The serializer sets sure'ascii = true so that
Escape the output so that the result string contains only ASCII characters.
The fields parameter specifies a subset of the serialized fields, or all data if not.

For more information, see Official documents

Use HttpResponse

Use HttpResponse() in view.py to return

return HttpResponse(data,content_type="application/json")

Browser view:

View in wechat developer tool:

To get the returned data, you only need to get the required value as follows:

var desc = res.data[0].fields.desc
var title = res.data[0].fields.title

Use JsonResponse

JsonResponse object:

JsonResponse(data,encoder=DjangoJSONEncoder,safe=True,json_dumps_params=None,** kwargs)
The default content type header is set to application/json
 data must be dict
 safe defaults to True. If set to False, any object can be passed for serialization.
Inherited from HttpResponse

Be careful:
Set safe=False or an error will be reported:
TypeError : In order to allow non-dict objects to be serialized set the safe parameter to False.
Of course, you can also write JsonResponse({data ': Data}) and pass in a dictionary type.

return JsonResponse(data,safe=False)

View in browser:

Obviously, the result is not satisfactory. But in the wechat developer tool, you can see that the json data it gets is of String type. We prefer to return the object type, because we take the expected desc or title from the String type
It's a lot of trouble.

Come from Python documentation Explain

Extensible JSON encoder for Python data structures.
Supports the following objects and types by default:

Python JSON
dict object
list, tuple array
str string
int, float number
True true
False false
None null

At a glance, the data we serialized is of str type (json encoding). This can be easily verified. So we expect to transform it into dict. Of course, don't expect to construct dict as follows: {'data': Data}. Its function is just like drawing a snake and adding a foot. You can use json.loads(data) to decode it. So the above code becomes:

return JsonResponse(json.loads(data),safe=False)

Hypothetical items

Suppose we have created a Django project / blogdemo and an application / blog. Here are some simple configurations to ensure that the project can start normally.

  • Registered apps in installed? Apps of setting.py
INSTALLED_APPS = [
    'blog', # Configuration application
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
  • Configure routing in urls.py
# Under blogdemo/blogdemo/urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',include('blog.urls')),    # Routing configuration
]

# Under blogdemo/blog/urls.py
urlpatterns = [
    path('wxapi/',views.wxapi,name='wxapi'),
]
  • Create a simple model in models.py
class Post(models.Model):
    auth = models.ForeignKey('Auth', on_delete=models.CASCADE)
    title = models.CharField(verbose_name="Title",max_length=50) 
    # The max'length property of CharField is required
    desc = models.CharField(verbose_name="Sketch",max_length=200,null=True,blank=True)
    def __str__(self):
        return self.title

class Auth(models.Model):
    name = models.CharField(verbose_name='Name',max_length=50)
    about = models.TextField(verbose_name='about',null=True,blank=False,default="No introduction")
    def __str__(self):
        return self.name
  • Write view function in views.py
def wxapi(request):
    posts = Post.objects.all()
    auth = Auth.objects.all()
    all = list(posts) + list(auth)
    # serialize
    data = serializers.serialize('json', all, ensure_ascii=False)
    return HttpResponse(data,content_type="application/json")

With the above configuration, you can basically start the project. Click http://127.0.0.1:8000/blog/wxapi/ to view

E:\Djangofiles\blogdemo>python manage.py makemigrations   # Model migration
E:\Djangofiles\blogdemo>python manage.py migrate
E:\Djangofiles\blogdemo>python manage.py runserver        # Startup project

Of course, there is no data on the page now, because no data has been added to the database. You can use the api side through the shell command window provided by Django
Type addition. You can also create an administrator account and add it by configuring the background. I won't go into details here.

summary

HttpResponse is more suitable for returning serializers, and JsonResponse is more suitable for returning custom dict type data.
It's not hard to find it from the JsonResponse source code, in which json.dumps() is used for the incoming data, while the previous use
json.loads processes the incoming data. The last data returned by JsonResponse is actually the same as HttpResponse. yes
No mistake, I did a fool operation here. It's like painting a snake with a foot (stupid cry. jpg). It's all my fault that when I see json, I think of JsonResponse.

Part of JsonResponse source code:

def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        if safe and not isinstance(data, dict):
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)
Published 6 original articles, won praise 0, visited 80
Private letter follow

Posted by JPark on Fri, 07 Feb 2020 07:01:23 -0800