Serialization of django-rest-framework,
Preface:I learned about rest-framework serialization yesterday, so I wrote a blog record. Official Website: http://www.django-rest-framework.org/tutorial/1-serialization/?working-with-serializers.
Frontend and backend Separation: Frontend development and backend development are separated. The implementation of this scheme is to use the API. In short, the API is called by others who provide the programming interface, and then return data for use. There are many types of APIS, but now the mainstream and practical is RESTful APIs.
I. Start
Okay, we're re ready to get coding. To get started, let's create a new project to work with. first create a Django project.
cd ~django-admin.py startproject tutorialcd tutorial
Once that's done we can create an app that we'll use to create a simple Web API. then create an APP
python manage.py startapp snippets
We'll need to add our newsnippets
App andrest_framework
AppINSTALLED_APPS
. Let's edittutorial/settings.py
File: Modify the global configuration file.
INSTALLED_APPS = ( ... 'rest_framework', 'snippets.apps.SnippetsConfig',)
Please note that if you're using Django <1.9, you need to replacesnippets.apps.SnippetsConfig
Withsnippets
.
If you are using Django <1.9, you need to changeSnippets. apps. SnippetsConfig is
snippets
.
Ii. Create a model
For the purposes of this tutorial we're going to start by creating a simpleSnippet
Model that is used to store code snippets (segment). Go ahead and editsnippets/models.py
File.
We will first createSnippet
Simple Model for storing code snippets, editingsnippets/models.py
File.
From django. db import models # Create your models here. # pygments can achieve code highlighted official website: http://pygments.org/from pygments. lexers import get_all_lexers # lexers: lexical analyzer from pygments. styles import get_all_stylesLEXERS = [item for item in get_all_lexers () if item [1] export age_choices = sorted ([(item [1] [0], item [0]) for item in LEXERS]) STYLE_CHOICES = sorted (item, item) for item in get_all_styles () class Snippet (models. model): created = models. dateTimeField (auto_now_add = True) # automatically add the creation time title = models. charField (max_length = 100, blank = True, default = '') code = models. textField () linnos = models. booleanField (default = False) language = models. charField (choices = LANGUAGE_CHOICES, default = 'python', max_length = 100) style = models. charField (choices = STYLE_CHOICES, default = 'dldly', max_length = 100) class Meta: ordering = ('created ',) # sort by creation time
Initialize and synchronize data to the database:
python manage.py makemigrations snippetspython manage.py migrate
3. Create a serialization class
The first thing we need to get started on our Web API is to provide a way of serializing (serialization) and deserializing (deserialization) the snippet instances into representations suchjson
. We can do this by declaring (Declaration) serializers that work very similar to Django's forms.
First, I want to ask you. Generally, when the front-end calls the background API, the API must return data to the front-end. What type of data is returned?
JSON is the most popular currently, and a small part of XML may still be used.
When learning django-rest-framework, is there any way to automatically convert data instance information to JSON? You can also convert the JSON data sent from the front end to the backend to the python data type (dict/list/set ...). Of course, serializers can be implemented. First, you must declare (introduce) The serializer. See the following example:
# The first thing to do with Web APIs is to provide a method of serializing and deserializing code snippet instances as a representation of json. # We can do this by declaring a serializer that is very similar to Django forms. Create a file in the directory named snippets, # serializers. py and add the following content from rest_framework import serializersfrom snippets. models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICESclass SnippetSerializer (serializers. serializer): # The first part of the Serializer class defines the serialization/deserialization fields. Id = serializers. integerField (read_only = True) title = serializers. charField (required = False, allow_blank = True, max_length = 100) # use the field flag to control the display template code = serializers when the serializer renders the HTML page. charField (style = {'base _ template': 'textarea.html '}) linnos = serializers. booleanField (required = False) language = serializers. choiceField (choices = LANGUAGE_CHOICES, default = 'python') style = serializers. choiceField (choices = STYLE_CHOICES, default = 'dldly') def create (self, validated_data): "The create () and update () methods define how fully fledged instances are created or modified when calling serializer. save () Create and return a new 'snippet 'instance, given the validated data. given the verified data, create and return a new Snippet instance "" return Snippet. objects. create (** validated_data) def update (self, instance, validated_data): "Update and return an existing 'snippet 'instance, given the validated data. given the verified data, update and return an existing Snippet instance "" instance. title = validated_data.get ('title', instance. title) instance. code = validated_data.get ('code', instance. code) instance. linnos = validated_data.get ('linano', instance. linux) instance. language = validated_data.get ('language ', instance. language) instance. style = validated_data.get ('style', instance. style) instance. save () # update return instance
The first part of the serializer class defines the serialization/deserialization fields. Thecreate()
Andupdate()
The method defines how an instance is created and updated.
The following line of code:
code = serializers.CharField(style={'base_template': 'textarea.html'})
What you need to know for the moment is that its function is to control the display template when the serializer renders the HTML page. As for why, it is particularly useful for controlling how to display the browsed API, this will be seen in later articles.
You can also useModelSerializer
To save your time, we will see later, Next let's take a look at the specific role of the serializer.
Iv. Use the serializer
Before learning more, we will be familiar with using our new Serializer class. Go to Django shell:
python manage.py shell
The next step is to create and save the Snippet model instance as you did when learning Django's ORM:
from snippets.models import Snippetfrom snippets.serializers import SnippetSerializerfrom rest_framework.renderers import JSONRendererfrom rest_framework.parsers import JSONParsersnippet = Snippet(code='foo = "bar"\n')snippet.save()snippet = Snippet(code='print "hello, world"\n')snippet.save()
When you view the database, you will find that there are two more rows of data in the relevant table, that is, the data we just created:
We now have several snippet instances to play. Let's take a look at serializing one of these instances.
serializer = SnippetSerializer(snippet)serializer.data# {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
At this point we 've translated the model instance into Python native PES ypes.
From the code above, we can see that we have converted the instance information of the model to the native data type of python, that is, the dictionary.
To finalize the serialization process we render the datajson
.
To complete the serialization process, we convert the datajson
.
content = JSONRenderer().render(serializer.data)content# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
The json format has already appeared. That is to say, the data in json format is to be displayed on a URL. You can probably feel that when we access a URL, the above heap of data will be returned for your use. This completes a serialization process and shows the prototype of the client.
Serialization is to return data in json format to the client for viewing and using data. When the client needs to modify, add, or delete data, the process should be reversed, that is, deserialization, deserializes the json format data submitted by the client.
Deserialization is similar. First, parse a stream to the Python local data type...
from django.utils.six import BytesIOstream = BytesIO(content)data = JSONParser().parse(stream)
... Then we restore those native PES ypes into a fully populated object instance.
Check whether the data is correct before saving the data:
serializer = SnippetSerializer(data=data)serializer.is_valid()# Trueserializer.validated_data# OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])serializer.save()# <Snippet: Snippet object>
In this case, another piece of data is added to the database:
We can also serialize querysets instead of model instances. To do so we simply addmany=True
Flag to the serializer arguments.
We can also serialize the query set rather than the model instance. To solve this problem, we only need to add a flag named "Success = True" to the serializer parameter.
serializer = SnippetSerializer(Snippet.objects.all(), many=True)serializer.data# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
5. Use ModelSerializers
In the above SnippetSerializer class, we inherit serializers. serializer class. We can see that many codes in the SnippetSerializer class are actually used with models. the Snippet model in py is similar, so we can improve it here. Just as the Form class and ModelForm class are provided in Django, django-rest-framework provides the Serializer class and ModelSerializer class for us. We can use it to make our code much simpler. Modify serializers. py:
# Our SnippetSerializer class is replicating a lot of information that's also contained in the Snippet model.# It would be nice if we could keep our code a bit more concise.class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
One nice property that serializers have is that you can inspect (check/view) all the fields in a serializer instance, by printing its representation. Open the Django shellpython manage.py shell
, Then try the following:
A good property of the serializer is that all fields in the serializer instance can be checked by printing its representation. Open Django shellpython manage.py shell
And then try the following operations:
from snippets.serializers import SnippetSerializerserializer = SnippetSerializer()print(repr(serializer))# SnippetSerializer():# id = IntegerField(label='ID', read_only=True)# title = CharField(allow_blank=True, max_length=100, required=False)# code = CharField(style={'base_template': 'textarea.html'})# linenos = BooleanField(required=False)# language = ChoiceField(choices=[('Clipper', 'FoxPro'), ('Cucumber', 'Gherkin'), ('RobotFramework', 'RobotFramework'), ('abap', 'ABAP'), ('ada', 'Ada')...# style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...
Remember, the ModelSerializer class does not do anything amazing. They are just shortcuts for creating the serializer class:
- A set of automatically determined fields.
- The create () and update () methods are implemented by default.
6. Compile a regular Django View
The next step is to use our new Serializer class to write some API views. Edit snippets/views. py:
from django.shortcuts import render# Create your views here.from django.http import HttpResponse, JsonResponsefrom django.views.decorators.csrf import csrf_exemptfrom rest_framework.renderers import JSONRendererfrom rest_framework.parsers import JSONParserfrom snippets.models import Snippetfrom snippets.serializers import SnippetSerializer@csrf_exemptdef snippet_list(request): """ because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as csrf_exempt List all code snippets, or create a new snippet. """ if request.method == "GET": snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == "POST": data = JSONParser().parse(request) serializer = SnippetSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400)@csrf_exemptdef snippet_detail(request, pk): """ Retrieve, update or delete a code snippet. """ try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return HttpResponse(status=404) if request.method == "GET": serializer = SnippetSerializer(snippet) return JsonResponse(serializer.data) elif request.method == "PUT": data = JSONParser().parse(request) serializer = SnippetSerializer(snippet, data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data) return JsonResponse(serializer.errors, status=400) elif request.method == 'DELETE': snippet.delete() return HttpResponse(status=204)
The above code is easy to understand and defines different operations in the background for different http actions, which also reflects the concept of restful API.
Because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the viewcsrf_exempt
.
Because we want to POST this view from clients that never have a CSRF token, we need to add a decorator to the view.csrf_exempt
To call the view function, you must design the url. The process here is the same as that in Django development. First create snippets/urls. py
from django.conf.urls import urlfrom snippets import viewsurlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),]
We also need to wire up the root urlconf, intutorial/urls.py
File, to include our snippet app's URLs.
from django.conf.urls import url, includeurlpatterns = [ url(r'^', include('snippets.urls')),]
7. Test APIs
After completing the above work, you can start the test. Exit the shell mode and start the server. To send a request according to the url we just designed, you must first install the httpie module:
pip install httpie
Then access the service in the command line window. The effect is as follows:
You can also access the data of the specified id:
Of course, you can also directly view it in the browser and enter the URL: