此章节将会介绍多种构成REST framework的重要模块,在每个部分如何一起配合上提供一个综合的全方面的了解。

准备

同样的创建一个新项目,创建一个新的app,将rest_framework跟新建的app加入到INSTALLED_APPS

创建工作model

打开新建的app的models.py文件

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, default='')
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',)

同步到数据库:

>>> python3 manage.py makemigrations
>>> python3 manage.py migrate

创建Serializer类

在开始web API时,首先需要做的就是提供一种序列化和反序列化的实例到表现的方式,例如json.

我们做这一步在申明serializers的时候跟Django的forms很相似。

创建一个serializers.py在app内

from rest_framework import serializers
from app01.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):
"""
用传入的验证过的数据validated_data,创建并返回新的Snippet实例
"""
return Snippet.objects.create(**validated_data) def update(self, instance, validated_data):
"""
用传入的验证过的数据validated_data,更新并返回Snippet实例
"""
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

第一部分关于serializer类定义了序列化和反序列化字段。create和update方法定义了当调用serializer.save()的时候全面的实例是如何被创建或者更改的。serializer 类跟Django的form类很相似,包含了相似的验证在不同的字段上,比如requeired、max_length、default.

字段表示也可以控制serializer应该如何显示在某一种场景下,比如render htm. style={'base_template': 'textarea.html'}等同于在form里面使用widget=widgets.Textarea. 这在控制可浏览的API如何显示方面很有用. 后面会再见讲到这些。

Serializers方面

在更进一步之前,先来熟悉一下Serializer类。打开Django的模拟环境shell.

shuais-MBP:TestApp dandyzhang$ python3 manage.py shell
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

首先到导入一些模块,创建一些实例

>>> from app01.models import Snippet
>>> from app01.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()

现在就有一些snippet实例测试了。

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

此时,转化这个model实例到python本身的数据类型。在结束序列化之前转换成json.

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

反序列化很类似。首先将流解析为Python本地数据类型。

>>> from django.utils.six import BytesIO
>>> stream = BytesIO(content)
>>> data = JSONParser().parse(stream)
>>> data
{'id': , 'title': '', 'code': 'print("hello, world")\n', 'linenos': False, 'language': 'python', 'style': 'friendly'}

然后,将这些原生数据类型还原为完全填充的对象实例。

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

注意API跟forms的使用非常的相似。它们之间的相似度在使用serializer来写views时会更加突出。

我们也可以序列化querysets来提到model的实例,如果想要这么做的话,添加一个many=True的标记在serializer.

>>> serializer = SnippetSerializer(Snippet.objects.all(), many=True)
>>> serializer.data
[OrderedDict([('id', ), ('title', ''), ('code', 'foo="bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
OrderedDict([('id', ), ('title', ''), ('code', 'print("hello, world")\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
OrderedDict([('id', ), ('title', ''), ('code', 'print("hello, world")'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]

使用ModelSerializers

SnippetSerializer类正在复制包含在Snippet模型中的大量信息。我们可以让代码更简洁一点。而同样地,Django提供了Form和ModelForm类,REST framework包含Serializer和ModelSerializer类。

用ModelSerializer类来重构一下serializer. 打开serializers.py文件,用下面的类代替SnippetSerializer.

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

serializers包含的一个很好的方面是,你可以检查所有的包含在serializer实例内的字段,通过打印它的表现。

打开Django的shell

>>> from app01.serializers import SnippetSerializer
>>> serializer = SnippetSerializer()
>>> print(repr(serializer))

值得记住的重要点是ModelSerializer类不做任何特别神奇的事情,它们只是创建序列化类的快捷方式:

a、一个自动确定的字段

b、create()update()方法简单的默认实现

使用Serializer撰写常规Django视图

一起看一下如何通过用新的Serializer类写一些API视图,从现在开始,不会用任何REST framework的其他的属性,只是像写普通的Django视图一样写这些视图。

编辑app01的视图views.py

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 app01.models import Snippet
from app01.serializers import SnippetSerializer

根目录API是一个视图,支持列出所有现存的snippets或者创建新的snippet.

@csrf_exempt
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True) # queryset
return JsonResponse(serializer.data, safe=False) # safe为True的时候只能传入字典的数据,不然会报错,而False可以传入任何可以被转换成JSON的对象 elif request.method == 'POST':
data = JSONParser().parse(request) # request对象的反序列化成字典
serializer = SnippetSerializer(data=data) # 字典传入
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)

我们还需要一个视图对应一个独立的snippet,可以用来获取、更新或者删除snippet

@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) # 单条数据对象直接丢进去,多条则是queryset类型,需要many=True
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) # 单个对象的data是一个字典  
return JsonResponse(serializer.errors, status=400) elif request.method == 'DELETE':
snippet.delete()
return HttpResponse(status=204)

最后修改urls

from app01 import views
from django.urls import path, include urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]

安装httpie:

pip3 install httpie

输入:

http http://127.0.0.1:8000/app01/snippets/

同样的也可以使用浏览器输入url得到同样的json数据

简单整理下,此篇blog的介绍流程

1、基础-创建model,同步数据库

2、创建serializers.py文件,创建serializers类,类似form验证表单的创建,继承form或者modelform,这里则继承Serializer

或者ModelSerializer,两者具有极高的相似度

3、通过shell模拟django环境,尝试一下serializer的用法。

4、FBV的方式实现了API的展示,返回Json序列化数据

Django REST framework 第一章 Serialization的更多相关文章

  1. Django REST framework 第二章 Request and Response

    此章节开始真正的撰写REST framework的核心代码,介绍一系列必要的建立设计 Request Objects REST framework介绍了一个Request对象用来扩展常规的HttpRe ...

  2. (转)Django学习之 第一章:Django介绍

    Django: Python编程Web框架 如果你上djangoproject.com你会发现对Django的如下解释: “Django is a high-level Python Web fram ...

  3. spring framework 第一章数据库管理(data access)

    spring data access 的网址:https://docs.spring.io/spring/docs/current/spring-framework-reference/index.h ...

  4. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  5. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

  6. 《Entity Framework 6 Recipes》翻译系列(2) -----第一章 开始使用实体框架之使用介绍

    Visual Studio 我们在Windows平台上开发应用程序使用的工具主要是Visual Studio.这个集成开发环境已经演化了很多年,从一个简单的C++编辑器和编译器到一个高度集成.支持软件 ...

  7. 第一章、Django概述

    目录 第一章.Django概述 一.了解软件开发架构 二.HTTP协议 三.响应状态码 四.请求方式 五.基于wsgiref模块 六..动静态网页 七.python三大主流web框架 八.安装Djan ...

  8. django rest framework 入门

    django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangop ...

  9. Python3+PyCharm+Django+Django REST framework开发教程

    一.说明 自己一是想跟上潮流二是习惯于直接干三是没有人可以请教,由于这三点经常搞得要死要活.之前只简单看过没写过Diango,没看过Django REST framework,今天一步到位直接上又撞上 ...

随机推荐

  1. Mybatis非mapper代理配置

    转: Mybatis非mapper代理配置 2017年04月26日 20:13:48 待长的小蘑菇 阅读数:870   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...

  2. centos 7 安装appache 服务器

    一.安装Apache程序,一般有三种安装方式:1.直接网络安装:2.下载rpm包,上传至服务器进行安装:3.通过原代码编译安装: yum -y install httpd rpm -qa | grep ...

  3. windows怎样查看被程序占用的端口

    1. netstat -ano  显示所有端口与任务管理器中的pid对应,通过pid打开任务管理器查询占用进程 附录:在命令行中输入netstat /? 可以查看netstat的相关信息.C:\Doc ...

  4. 【清北学堂2018-刷题冲刺】Contest 1

    Task 1:最小公倍数  输入n,求n与246913578的最小公倍数.  结果对1234567890取模. [样例输入] 3 [样例输出] 246913578 [数据规模和约定] 对于30%的数据 ...

  5. cookie猜数字游戏(上)---------------思路分析(踩坑)

    说明:用户第一次请求页面的时候,同时会产生一个随机数,用户点提交表单的时候,会将输入的数字与第一次请求产生的数字进行一个对比. 问题一:如何保存用户每次提交的数据 我们常见的在服务器中保存数据的方式是 ...

  6. SQLMAP UDF提权

    SQLMAP UDF提权      1.连接mysql数据打开一个交互shell: sqlmap.py -d mysql://root:root@127.0.0.1:3306/test --sql-s ...

  7. hibernate注解方式来处理映射关系

    在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式 ...

  8. Web API中的内容协商

    一.内容协商的概念 HTTP规范将内容协商定义为“当有多个格式可用时为给定响应选择最佳格式的过程”.HTTP中内容协商的主要机制是这些请求标头: Accept:响应可接受哪些媒体类型,例如“appli ...

  9. 解决ubuntu中arm-linux-gcc not found

    1. 注意检查是不是 换了bash的原因 2. 此外还有权限切换以后环境变量换了 3.如果遇到环境变量配置以后,能够找到版本(也就是说 输入 命令的开头按tab以后能够出现补全),这是因为64位下运行 ...

  10. STM32学习笔记:【002】BIN文件通过ST-LINK烧录STM32芯片

    以下提供2种下载方式 KEIL编译下载 KEIL 5 在开发中还算是比较强大的一种平台.在开发中通过编译再下载会显得很方便. 尽管这个是老生常谈的问题,但还是在这里补全这个设置步骤 1.点击“魔法棒” ...