django rest framework personal learning notes (2) - Tutorial 1. Serialization

Keywords: Python Django REST JSON

Serialization -- serialization

Official website address

Preface

This tutorial will introduce the creation of a simple web API. Throughout the learning process, the various components of the REST framework will be introduced one by one to give you a comprehensive understanding of all things if combined.
This tutorial will be quite detailed, so before you start, you should go for some biscuits and drink some of your favorite drinks. If you just want a quick overview, you should check it out Quickstart.
Note: The code for this tutorial is available in GitHub tomchristie/rest-framework-tutorial Found in. test This is a test link.

Create a new virtual environment

Use virtualenv Create a virtual environment.

virtualenv env
source env/bin/activate

Then we install the required packages in the virtual environment we created.

pip install django
pip install djangorestframework
pip install pygments #Use it to highlight code

Note: Use deactivate to exit the virtual environment at any time. For more information, please check Virtualenv documentation

Get ready

We're starting to write code here. Let's create a project first.

cd ~
django-admin.py startproject tutorial
cd tutorial

Next, we create an app.

python manage.py startapp snippets

We need to add snippets and rest_framework to INSTALLED_APPS in the tutorial/settings.py file:

INSTALLED_APPS = {
    ...
    'rest_framework',
    'snippets.apps.SnippetsConfig',
}

Note: If you use Django < 1.9, you need to replace snippets. apps. Snippets Config with snippets.
We can go on.

Create model

In this tutorial, we will create a simple model that will be used to store code snippets.
Edit the snippets/models.py file.
Note: It's a good habit to write notes.

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_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)
    title = models.CharField(max_length=100,blank=True,defalut='')
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES,default='python',max_length=100)
    style = models.CharField(choices=STYLE_CHOICES,default='friendly',max_length=100)
    
    class Meta:
        ordering = ('created')

Execute commands to create data tables:

    python manage.py makemigrations snippets
    python manage.py migrate

Create Serializer

First, we need to provide a serialized and deserialized presentation of our web API, such as json.
We can declare a serializers similar to django's forms. Create a Serializers.py file.

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES

class SnippetSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False,allow_blank=True,max_length=100)
    code = serializers.CharField(style={"base_template":"textarea.html"})
    linenos = serializers.BooleanField(required=False)
    language = serializers.ChoiceField(choices=LANGUAGE_CHOICES,default='python')
    style = serializers.ChoiceField(choices=STYLE_CHOICES,default='friendly')
    
    def create(self,validated_data):
        return Snippet.objects.create(**validated_data)
       
    def update(self,instance,validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

The first step in serializer is to define the fields that need to be serialized / deserialized. The create() and update() methods define if serializer.save() is created and updated.
The serializer class is very similar to Django's Form class. Includes validation tags for various fields, such as required,max_length,default.
Field tags can also control how serializer s are displayed in certain environments, such as rendering as HTML.
The previous {base_template':'textarea. html'} tag corresponds to widget=widgets.Textarea` in django Form.

In fact, we can save more time by using the ModelSerializer class, but for now, we still display the fields that define us.

Start-up

Before we go any further, we will familiarize ourselves with serializer through the django shell.

python manage.py shell

We need to import what we need and then create two snippet s.

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

snippet = Snippet(code='foo="bar"\n')
snippet.save()

snippet = Snippet(code='print "hello, world"\n')
snippet.save()

Let's take a look at one of the examples we created:

serializer = SnippetSerializer(snippet)
serializer.data
# {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}

Here, we translate the model instance as python's native data type, and in order to complete serialization, we present the data as JSON.

content = JSONRenderer().render(serializer.data)
content
# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'

Deserialization is similar. First, we parse a stream as a Python native data type.

from django.utils.six import BytesIO
data = JSONParser().parse(stream)

Then we restore the native data type to a fully populated object instance.

serializer = SnippetSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
# <Snippet: Snippet object>

Note: This is similar to forms. When we write views using serializer, it will look more similar.

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')])]

Using Model Serializers

Our SnippetSerializer class copies a lot of snippet stuff. We want our code to be clean and tidy.
Similar to django, which has Form and ModelForm classes, the REST framework also contains Serializer and ModelSerializer classes.
Let's use ModelSerializer to refactor our serializer class. Open snippets/serializers.py and replace the SinppetSerializer class:

class SnippetSerializer(serializers.ModelSerizer):
    class Meta:
        model = Snippet
        fields = ('id','title','code','linenos','language','style')

Serializer has a nice property that allows you to view all fields of a serializer instance by printing. Open the Django shell (python management. py shell):

from snippets.serializers import SnippetSerializer
serializer = 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')...

Note: Model Serializer doesn't do anything magical, it just creates serializer faster

  • Automatically determine field settings
  • Simple default create() and update() methods

Write a regular django views using Serializer

Let's use our new serializer to write some API views. Here, instead of using any other features of the REST framework, we write a regular django views.
Write snippets/views.py file:

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer

Our API will support viewing all data and creating a new snippet

@csrf_exempt
def snippet_list(request):
    """
    //Display 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)

Note: Because we want post to fail CSRF token validation, we use csrf_exempt. In fact, this is not something you often do, and REST framework views will do it more wisely. But now, he can use it.

We also need this view to be retrievable, updated, and deleted.

@csrf_exempt
def 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)

Finally, we need to create URLs in the snippets/url s.py file

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

We also need to introduce our urls.py(tutorial/urls.py) to urls.py.

from django.conf.urls import url, include

urlpatterns = [
    url(r'^', include('snippets.urls')),
]

Note: There are some problems with our view that have not been properly handled, such as the incorrect json format sent or the method invoked that the view does not have, then we will return a 500 "server error" message.

Posted by pornophobic on Tue, 01 Jan 2019 16:00:08 -0800