此章节将会介绍多种构成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. 安全测试之Top 10 漏洞的分析

    1. 问题:没有被验证的输入  测试方法: 数据类型(字符串,整型,实数,等) 允许的字符集 最小和最大的长度 是否允许空输入 参数是否是必须的 重复是否允许 数值范围 特定的值(枚举型) 特定的模式 ...

  2. Appium的图像界面浅说

    appium的图形用户界面(GUI) (1)Application中各个项的含义作用: Application Path:填写你需要测试的Android APK的包地址(两种方式:1直接点击Choos ...

  3. js中两种定时器,setTimeout和setInterval的区别

    setTimeout只在指定时间后执行一次,代码如下:   <script>   //定时器 异步运行   function hello(){   alert("hello&qu ...

  4. 解决access 导出 excel 字段截断错误的问题

    解决方法:这个问题通过从EXCEL中导入外部数据,也就是ACCESS数据可以解决. 1.选择导入数据 2.点击选择数据源 选择需要导入的access数据源

  5. (二叉树 BFS DFS) leetcode 104. Maximum Depth of Binary Tree

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...

  6. apache thrift分析

    thrift是一个用来实现跨语言的远程调用(RPC Remote Procedure Call)的软件框架.根据接口定义语言(IDL Interface definition lanuage) 并借助 ...

  7. 干货分享:互联网运营 学习SEO从零开始 SEO深度解析学习笔记

    最近在自学SEO,互联网运营,把做的笔记干货分享给大家啊! 希望能帮到大家,如有好的建议可以关注我[磨人的小妖精]或留言,大家一起探讨. 之前还写过一篇文章互联网运营+SEO:推荐必看的5本书籍,学习 ...

  8. 剑指Offer_编程题_17

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构)   /* struct TreeNode { int val; struct TreeNode * ...

  9. Spring_事务管理

    转自:https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html 事务管理是应用系统 ...

  10. IDEA DEBUG无法启动

    如题:idea DEBUG无法启动 解决方法: 1.查找出占用进程id 2.杀死进程 cmd 输入 命令: 1.netstat -ano|findstr 4405 2.taskkill -f -pid ...