Django Rest Framework Serializer的简单使用

1.RESTful

1.1 定义

REST(Representational State Transfer)与技术无关,代表一种软件架构风格,中文为表征状态转移。

1.2 RESTful API设计

  • API与用户的通信协议,总是使用HTTPS协议
  • 域名
  • 版本
  • 路径,网络上的任何东西都是资源,均使用名词表示(可复数)
  • method
    • GET :从服务器取出资源(一项或多项)
    • POST:在服务器新建一个资源
    • PUT:在服务器更新资源(客户端提供改变后的完整资源)
    • PATCH:在服务器更新资源(客户端提供改变属性)
    • DELETE:从服务器删除资源
  • 过滤,通过在url上传递参数的形式传递过滤条件
  • 状态码

    常见状态码:

    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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  • 错误信息,状态码是4xx时,应该返回错误信息,error当做key
    {
      error:"Invalid API key"
    }
  • 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
    GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    

2.Django Rest Framework 框架

Django Rest Framework帮助我们快速构建符合RESTful的数据。通常用于前后端分离项目之间的数据资源传输。

2.1 Serializer的简单使用

serializers序列化器,帮助我们快速序列化在数据库中查询到的数据。

下面通过一个小例子来简单看一下Serializer的使用

表结构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')

路由urls.py

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

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

2.1.1 通过json模块手动序列化

views.py文件

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序列化

通过json手动序列化,当数据中有时间类型时,序要单独处理成字符串类型,才能进行序列化。

2.1.2 通过django的JsonResponse

views.py文件

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类不能对查询到的query_set对象直接序列化,对外键等字段关联对象数据不好处理。

2.1.3 使用django自带的序列化器

views.py文件

#使用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)

序列化后的数据格式

[
  {
    "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 使用Rest Framework的Response对象

views.py文件

#使用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)

数据格式

[
    {
        "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.py文件

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文件

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

数据格式:

[
    {
        "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实现简单的增删改

urls.py文件

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 获取多条数据和添加数据

serializer.py文件

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文件

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的数据

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

返回的数据

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

2.2.2 获取单条数据、编辑和修改

serializer.py文件

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文件

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的数据

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

返回的数据

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

原文地址:https://www.cnblogs.com/wang-kai-xuan/p/11247496.html

时间: 2024-10-28 03:38:03

Django Rest Framework Serializer的简单使用的相关文章

Django REST framework 单元测试

Django REST framework 单元测试 只是简单记录一下测试代码怎么写 环境 Win10 Python3.7 Django2.2 项目 参照官网 快速开始 写了一个 demo 测试 参照官网 测试 和 Django 的测试差不多 创建 tutorial/tests/tests.py import json from django.test import TestCase from rest_framework import status from rest_framework.te

【Django】Django REST Framework简单教程

Django REST Framework使用案例和教程 什么是Django REST Framework?简单说就是一款快速构建REST风格API的框架.能够以很少的代码和很简单的方式在Django项目中构建符合REST风格的API.十分适合Django框架的后端的编写 本文参考 https://blog.csdn.net/weixin_40193776/article/details/81210215,教程原文非常详细,还带图片.本文做了顺序上的修改以符合从无到有建立REST Framewo

Django REST framework 的TokenAuth认证及外键Serializer基本实现

一,Models.py中,ForeignKey记得要有related_name属性,已实现关联对象反向引用. app_name = models.ForeignKey("cmdb.App",related_name='deploy_app', verbose_name="App") 二,Settings.py文件中,加入对Django REST framework的基本设置. REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSE

利用 Django REST framework 编写 RESTful API

利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framework 真乃一大神器,可以轻易的甚至自动化的搞定很多事情,比如: 自动生成符合 RESTful 规范的 API 支持 OPTION.HEAD.POST.GET.PATCH.PUT.DELETE 根据 Content-Type 来动态的返回数据类型(如 text.json) 生成 browserable

django rest framework 入门

django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangopythonrest framework ************************************ 广告时间: 海淘导航网站推荐:海淘库:http://www.haitaocool.com/ 需要的请收藏哦 ************************************ 1.

Django Rest framework序列化流程

目录 一 什么是序列化 二 Django REST framework配置流程之Serializer 三 Django REST framework配置流程之ModelSerializer 一 什么是序列化 序列化模型与序列化关系模型 序列化模型,顾名思义,即对 models 里的数据模型作序列化. 而序列化关系模型则是对 models 里数据模型中带有关系的如 ForeignKey, ManyToManyField 和 OneToOneField 字段作序列化. Django Rest Fra

Django Rest Framework源码剖析(八)-----视图与路由

一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使用者而言不同的视图具有不同的功能,这样我们可以根据需求定制自己视图.以下是官网传送门:http://www.django-rest-framework.org/api-guide/views/ 在之前的文章中,由于参杂了权限.认证等(如果不了解请看博客的以前的文章),但在本章中基本可以不使用,所进使

DRF (Django REST framework) 框架介绍(2)

环境安装与配置 DRF需要以下依赖: Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6) Django (1.10, 1.11, 2.0) DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建.(若没有Django环境,需要先创建环境安装Django) 1. 安装DRF pip install djangorestframework 2. 添加rest_framework应用 我们利用在Django框架学习中创建的demo工

DRF (Django REST framework) 框架介绍

Web应用模式 在开发Web应用中,有两种应用模式: 前后端不分离 前后端分离 1 前后端不分离 在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高. 这种应用模式比较适合纯网页应用,但是当后端对接App时,App可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不再适用于前端App应用,为了对接App后端还需再开发一套接口. 2 前后端分离 在前后端分离的应用模式中,后端仅返