官方文档地址:http://www.django-rest-framework.org/tutorial/1-serialization/
1.什么是序列化
官方定义:串行器允许诸如查询集和模型实例复杂的数据转换为可随后被容易地呈现到机Python数据类型JSON
,XML
或其他内容类型。序列化程序还提供反序列化,允许在首次验证传入数据后将解析后的数据转换回复杂类型。REST框架中的序列化程序与Django Form
和ModelForm
类的工作方式非常相似。我们提供了一个Serializer
类,它为您提供了一种强大的通用方法来控制响应的输出,以及一个ModelSerializer
类,它提供了一个有用的快捷方式来创建处理模型实例和查询集的序列化程序。
其实序列化就是将我们实例化的对象变成json数据的过程,这个过程的实现其实很简单,总结起来就是(1)创建一个model也就是一张数据表(2)在项目app下定义一个序列化的类,你想序列化哪个表,想序列化哪个字段,就写哪个字段,具体怎么写下面我们按照官方文档来(3)根据数据表实例化一个对象(4)使用你创建的序列化的类对这个实例化的对象进行序列化
2.为什么要序列化,有什么用
学习一个新的技术就要知道为什么要学习,学习之后有什么作用。作为一个后端工程师,经常需要做的工作就是把数据从数据库中拿出来,然后返回给前端,前端再去操作这些数据,但是数据直接返回给前端是不行的,因为前端工程师需要的是json 数据,这时候就需要用到序列化,也就是将数据表中的各个字段和值转化为json 格式的数据。
3.实际项目操作
关于序列化官方给出了英文文档,虽然很完善,但是并不容易看明白,下面就是我按照英文文档对项目进行的一模一样的操作以及对它的理解
(1)进行序列化操作需要的框架
django,djangorestframework这是项目中需要用到的框架,安装起来也很容易(必须安装)
pip install django
pip install djangorestframework
(2)创建项目以及项目app
django-admin startproject tutorial
python manage.py startapp snippets
创建一个名为tutorial的项目,以及项目下面一个名为snippets的app
(3)在settings中配置我们的app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'snippets.apps.SnipprtsConfig',
]
这里我们按照官方给出的步骤配置好settings
(4)操作项目的模板(snippets/models.py)
from django.db import models
# Create your models here.
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)
class Meta:
ordering = ('created',)
这里跟官方文档有一点区别,官方文档的创建的数据表有language和style两个字段,这里我省略了,并没有任何影响
(5)创建一个序列化的类
这一步需要手动添加一个py文件,在snippets这个app下面创建一个serializers.py文件,创建之后就在这个文件中创建序列化的类
serializers.py
from rest_framework import serializers
from snippets.models import Snippet
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_templates':'textarea.html'})
linenos = serializers.BooleanField(required=False)
class Meta:
model = Snippet
fields = ('id','title','code','linenos')#序列化之后需要返回的字段('__all__'为所有字段)
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.save()
return instance
这一步虽然看起来有些不明白,但是仔细揣摩也很简单,我们首先在models.py中创建了一个叫做Snippet的数据表,然后我们就在这里创建一个叫做SnippetSerializer的用来序列化数据表的类;数据表继承了models.Model这个类,那序列化的这个类就继承serializers.Serializer这个类;数据表中有title,code,linenos这些字段,那我们想序列化这些字段就同样的在SnippetSerializer中也创建这些字段,只不过是把数据表中字段的model变成serializers;在序列化的类中我们用到了fields,它的作用就是指定我们序列化之后想返回给前端的数据的字段也就是属性有哪些fields = '__all__'为所有字段.
(6)创建一个对象来体验一下序列化的过程
这里使用python的shell 终端下输入python manage.py shell进入shell
进入之后我们需要引入一系列的包,代码如下(这些代码都是在shell下一行一行写的)
from rest_framework.renderers import JSONRenderer #这个包用来将数据渲染成json字节流形式
from snippets.models import Snippet #引入我们创建的Snippet数据表
from snippets.serializers import SnippetSerializer #引入我们创建的用来序列化的类
from rest_framework.parsers import JSONParser #引入从数据中解析出json对象的包
引入之后就是实例化一个对象,然后再对这个对象序列化
snippet = Snippet(code='print "hello,world"\n')#实例化一个对象并设置字段的值
snippet.save()保存这个对象
snippet = Snippet(code='foo = "bar"\n')实例化第二个对象
snippet.save()保存这个对象
serializer = SnippetSerializer(snippet)#创建一个序列化对象,用来序列化上一步创建的snippet对象
serializer.data #查看序列化对象中的数据
content = JSONRenderer().render(serializer.data)#将数据渲染成json数据
content #输出数据
这里我们就已经序列化了一个对象,可以观察输出的数据为json格式的数据
(7)操作视图函数
snippets/views.py文件
from django.shortcuts import render
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
# Create your views here.
@csrf_exempt
def snippet_list(request):
if request.method == 'GET':
snippets = Snippet.objects.all() #获取所有的创建的实例化对象
serializer = SnippetSerializer(snippets,many=True) #将实例化的对象序列化,如果获取到多个数据需要添加many=True
return JsonResponse(serializer.data,safe=False) #将序列化的数据作为json 数据返回
# return JSONRenderer().render(serializer.data) #将json数据渲染成字节流(需要注意的是用GET请求不会返回字节流,会出现异常)
elif request.method == 'POST':
data = JSONParser().parse(request)#从字符串中解析出json对象
serializer = SnippetSerializer(data=data)#序列化这个json对象
if serializer.is_valid(): #判断序列化的数据是否合法,必须判断
serializer.save()
return JsonResponse(serializer.data,status=201)
return JsonResponse(serializer.errors,status=400)
@csrf_exempt
def snippet_detail(request,pk):
try:
snippet = Snippet.objects.get(pk=pk)#从url中获取需要操作的id,如果没有则抛出异常返回404状态
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)#从字符串中解析出json对象
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)
视图函数官方文档定义了两个:snippet_list用来展示所有序列化之后的数据;snippet_detail根据url中传入的id来获取某一个json数据。
(8)配置url
tutorial/urls.py 跟路由
"""tutorial URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^',include('snippets.urls')),
]
snippets/urls.py 二级路由
from django.conf.urls import url
from snippets import views
urlpatterns = [
url(r'^snippets/$',views.snippet_list),
url(r'^snippets/(?P[0-9]+)/$',views.snippet_detail),
]
(9)启动项目
python manage.py runserver(也可以用pycharm专业版启动)
(10)测试我们的第一个Web API
这里官方文档给出的测试方法是使用httpie,首先需要安装httpie
pip install httpie
然后我们一步一步来测试,首先获取所有序列化数据
http http://127.0.0.1:8000/snippets/(一定注意最后的斜杠不要省略)
如图,这就是返回给我们的json数据,接着我们获取某个id的数据
也同样能够得到json数据
同样,在浏览器中输入127.0.0.1:8000/snippets/能够获得所有序列化的数据,输入127.0.0.1:8000/snippets/2/能够获得id=2的json数据