Simple to use Django Rest Framework Serializer of

1.RESTful

1.1 Definitions

REST (Representational State Transfer) has nothing to do with technology, it represents a style of software architecture, to characterize the Chinese state transition.

1.2 RESTful API design

  • API and user communication protocol, always use the HTTPS protocol
  • domain name
  • version
  • Path, anything on the network all resources, both use nouns denote (can be plural)
  • method
    • GET: Remove the resource (one or more) from the server
    • POST: Create a new resource on the server
    • PUT: update the resource on the server (after complete resources provided by the client to change)
    • PATCH: updated resource on the server (provided by the client to change the attributes)
    • DELETE: delete a resource from the server
  • Filtered, passed through a filter condition in the form of passing parameters url
  • status code

    Common status codes:

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  • Error messages, status code is 4xx, it should return an error message, error as key

    {
      error:"Invalid API key"
    }
  • Return results for different operations, the results returned by the server to the user should meet the following specifications

    GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    

2.Django Rest Framework Framework

Django Rest Framework help us meet the rapidly build RESTful of data. Commonly used for data transmission between the front and rear ends resources separating items.

Simple use of 2.1 Serializer

serializers serializer, help us quickly serialized in a database query to the data.

By following a simple look at a small example to use the Serializer

Table structure model.py

from django.db import models

# Create your models here.
class Publisher(models.Model):
    name = models.CharField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32, )


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=6, decimal_places=2)
    pub_date = models.DateTimeField()
    pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
    authors = models.ManyToManyField('Author')

Routing urls.py

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

urlpatterns = [
    url(r'^books/', views.BookListView.as_view()),
]

2.1.1 manually json serialization module

views.py file

from django.shortcuts import render, HttpResponse
from django.views import View
import json

#使用json模块序列化,时间类型需要单独转成字符串再序列化
class BookListView(View):
    def get(self, request, *args, **kwargs):
        obj_list = models.Book.objects.all().values('title', 'pub', 'pub_date')
        return HttpResponse(json.dumps(list(obj_list), ensure_ascii=False))  # pub_date为日期类型无法json序列化

By manually json serialization time when the data type, into a single sequence string type to be processed to be serialized.

2.1.2 django by the JsonResponse

views.py file

from django.http.response import JsonResponse

#使用JsonResponse对象序列化,可以直接处理时间类型
class BookListView(View):
    def get(self, request, *args, **kwargs):
        obj_list = models.Book.objects.all().values('title', 'pub', 'pub_date')
        return JsonResponse(list(obj_list), safe=False, json_dumps_params={
            'ensure_ascii': False})  # safe参数为False:当最外层不为字典时也可序列化,json_dumps_params参数:设置json序列化的参数

JsonResponse class can not be directly serialize queried query_set objects, the object data associated with the foreign key field not treated like.

2.1.3 django own serializer

views.py file

#使用django自带的序列化器
from django.core import serializers
class BookListView(View):

    def get(self, request, *args, **kwargs):
        """ 获取所有的数据  返回所有的书籍数据 json格式"""
        # 1. 从数据库获取所有数据
        all_books = models.Book.objects.all()

        data = serializers.serialize('json', all_books)
        return HttpResponse(data)

Serialized data format

[
  {
    "model": "app01.book",
    "pk": 1,
    "fields": {
      "title": "\u4e5d\u9634\u771f\u7ecf",
      "price": "9.99",
      "pub_date": "2019-06-04T07:15:56Z",
      "pub": 1,
      "authors": [
        1,2
      ]
    }
  },
  {
    "model": "app01.book",
    "pk": 2,
    "fields": {
      "title": "\u4e5d\u9633\u771f\u7ecf",
      "price": "98.30",
      "pub_date": "2019-04-16T07:16:39Z",
      "pub": 1,
      "authors": [
        1
      ]
    }
  },
  {
    "model": "app01.book",
    "pk": 3,
    "fields": {
      "title": "\u8475\u82b1\u5b9d\u5178",
      "price": "65.50",
      "pub_date": "2019-07-25T07:17:09Z",
      "pub": 2,
      "authors": [
        2
      ]
    }
  }
]

2.1.4 Response object's Rest Framework

views.py file

#使用RestFramework 的response对象
from rest_framework.views import APIView
from rest_framework.response import Response

class BookListView(APIView):
    def get(self, request, *args, **kwargs):
        all_books = models.Book.objects.all().values('title', 'authors__name','pub_date')
        print(all_books)
        return Response(all_books)

Data Format

[
    {
        "title": "九阴真经",
        "authors__name": "沙和尚",
        "pub_date": "2019-06-04T07:15:56Z"
    },
    {
        "title": "九阴真经",
        "authors__name": "猪悟能",
        "pub_date": "2019-06-04T07:15:56Z"
    },
    {
        "title": "九阳真经",
        "authors__name": "沙和尚",
        "pub_date": "2019-04-16T07:16:39Z"
    },
    {
        "title": "葵花宝典",
        "authors__name": "猪悟能",
        "pub_date": "2019-07-25T07:17:09Z"
    }
]

2.1.5 Rest Framework serializer

First create a serializer

serializer.py file

from rest_framework import serializers

class AuthorSerializer(serializers.Serializer): #Author表的序列化器
    name = serializers.CharField()

class PublisherSerializer(serializers.Serializer): #Publisher表的序列化器
    name = serializers.CharField()

class BookSerializer(serializers.Serializer): #Book表的序列化器
    title = serializers.CharField() #普通字段类型和数据库类型相同即可,字段名也要相同
    price = serializers.DecimalField(max_digits=6,decimal_places=2)
    pub_date = serializers.DateTimeField()
    pub = PublisherSerializer()  #外键使用,使用定义的序列化器实例化
    authors = serializers.SerializerMethodField() #多对多字段,定义get_字段名方法

    def get_authors(self,obj): #obj当前表的对象
        data_obj = AuthorSerializer(obj.authors.all(),many=True) #多条数据要设置many为True
        return data_obj.data #返回对象的data

views.py file

class BookListView(APIView):
    def get(self, request, *args, **kwargs):
        all_books = models.Book.objects.all()
        ser_obj = BookSerializer(all_books, many=True)#多条数据要设置many为True

        return Response(ser_obj.data)#返回对象的data

Data Format:

[
    {
        "title": "九阴真经",
        "price": "9.99",
        "pub_date": "2019-06-04T07:15:56Z",
        "pub": {
            "name": "沙和尚出版社"
        },
        "authors": [
            {
                "name": "沙和尚"
            },
            {
                "name": "猪悟能"
            }
        ]
    },
    {
        "title": "九阳真经",
        "price": "98.30",
        "pub_date": "2019-04-16T07:16:39Z",
        "pub": {
            "name": "沙和尚出版社"
        },
        "authors": [
            {
                "name": "沙和尚"
            }
        ]
    },
    {
        "title": "葵花宝典",
        "price": "65.50",
        "pub_date": "2019-07-25T07:17:09Z",
        "pub": {
            "name": "二师兄出版社"
        },
        "authors": [
            {
                "name": "猪悟能"
            }
        ]
    }
]

2.2 Serializer simple additions and deletions

urls.py file

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

urlpatterns = [
    url(r'^books/', views.BookListView.as_view()), #获取多条数据和添加数据
    url(r'^book/(\d+)/', views.BookView.as_view()), #获取单条数据,编辑和删除数据
]

2.2.1 acquire pieces of data and adding data

serializer.py file

from rest_framework import serializers
from app01 import models


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField()


class PublisherSerializer(serializers.Serializer):
    name = serializers.CharField()


class BookSerializer(serializers.Serializer):
    title = serializers.CharField()
    price = serializers.DecimalField(max_digits=6, decimal_places=2)
    pub_date = serializers.DateTimeField()
    pub = PublisherSerializer(read_only=True) #GET请求时需要的数据设置为只读,POST时可为空
    authors = serializers.SerializerMethodField(read_only=True)
    post_pub = serializers.IntegerField(write_only=True) #POST和PUT时的数据只写,GET时可为空
    post_authors = serializers.ListField(write_only=True)

    def get_authors(self, obj):
        data_obj = AuthorSerializer(obj.authors.all(), many=True) #多个对象需要many为True
        return data_obj.data

    def create(self, validated_data):  #create方法用于添加数据,validated_data校验完的数据 
        book_obj = models.Book.objects.create(
            title=validated_data.get('title'),
            price=validated_data.get('price'),
            pub_date=validated_data.get('pub_date'),
            pub_id=validated_data.get('post_pub'),
        )
        book_obj.authors.set(validated_data.get('post_authors'))
        return book_obj  # 将book对象返回

view.py file

from app01.serializer import BookSerializer
class BookListView(APIView):
    def get(self, request, *args, **kwargs):
        all_books = models.Book.objects.all()
        obj = BookSerializer(all_books,many=True)
        return Response(obj.data)

    def post(self,request,*args,**kwargs):
        print(request.data)
        obj = BookSerializer(data=request.data)
        if obj.is_valid(): #对数据进行校验,貌似序列化器里的多对多不会校验
            obj.save()  #会去序列化器里找create()方法
            return Response(obj.data) #校验成功返回添加的数据
        return Response({'error': obj.errors}) #校验失败返回错误信息

POST data

{
  "title": "葵花宝典续集",
  "price": "65.50",
  "pub_date": "2019-07-25T07:17:09Z",
  "post_pub": 1,
  "post_authors": [
      1
  ]
}

The data returned

{
    "title": "葵花宝典续集",
    "price": "65.50",
    "pub_date": "2019-07-25T07:17:09Z",
    "pub": {
        "name": "沙和尚出版社"
    },
    "authors": [
        {
            "id": 1,
            "name": "沙和尚"
        }
    ]
}

2.2.2 single data acquisition, editing and revision

serializer.py file

class BookSerializer(serializers.Serializer):
    title = serializers.CharField()
    price = serializers.DecimalField(max_digits=6, decimal_places=2)
    pub_date = serializers.DateTimeField()
    pub = PublisherSerializer(read_only=True)
    authors = serializers.SerializerMethodField(read_only=True)
    post_pub = serializers.IntegerField(write_only=True)
    post_authors = serializers.ListField(write_only=True)

    def get_authors(self, obj):
        data_obj = AuthorSerializer(obj.authors.all(), many=True)
        return data_obj.data

    def create(self, validated_data):  # validated_data校验完的数据
        book_obj = models.Book.objects.create(
            title=validated_data.get('title'),
            price=validated_data.get('price'),
            pub_date=validated_data.get('pub_date'),
            pub_id=validated_data.get('post_pub'),
        )
        book_obj.authors.set(validated_data.get('post_authors'))
        return book_obj  # 将book对象返回

    def update(self, instance, validated_data):  # 修改数据时调用update方法,instance当前要求改的数据对象
        instance.title = validated_data.get('title', instance.title)
        instance.price = validated_data.get('price', instance.price)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        instance.pub_id = validated_data.get('post_pub', instance.title)
        instance.save()
        instance.authors.set(validated_data.get('post_authors',instance.authors.all()))
        return instance #返回修改后的数据对象

view.py file

class BookView(APIView):
    def get(self, request,pk, *args, **kwargs):
        book = models.Book.objects.filter(pk=pk).first()
        obj = BookSerializer(book)
        return Response(obj.data)

    def put(self,request,pk,*args,**kwargs): #修改资源
        book = models.Book.objects.filter(pk=pk).first()
        obj = BookSerializer(data=request.data,instance=book)
        if obj.is_valid():
            obj.save() #保存时会调用序列化器定义好的update()方法
            return Response(obj.data) #校验成功返回修改后的对象
        return Response(obj.errors)

    def delete(self,request,pk,*args,**kwargs): #删除资源
        book = models.Book.objects.filter(pk=pk).first()
        if book:
            book.delete()
            return Response({'info':'删除成功'})
        return Response({'info': '数据不存在'})

PUT data

{
  "title": "葵花宝典1",
  "price": "63.50",
  "pub_date": "2019-07-25T07:17:09Z",
  "post_pub": 1,
  "post_authors": [
      1
  ]
}

The data returned

{
    "title": "葵花宝典1",
    "price": "63.50",
    "pub_date": "2019-07-25T07:17:09Z",
    "pub": {
        "name": "沙和尚出版社"
    },
    "authors": [
        {
            "id": 1,
            "name": "沙和尚"
        }
    ]
}

Guess you like

Origin www.cnblogs.com/wang-kai-xuan/p/11247496.html
Recommended