Django-rest-framework (一)、序列化
2018-03-31 09:11
465 查看
序列化
django-rest-framework serializer可以很方便的实现model对象的序列化,对前端传递的数据进行验证等等,功能与django原生的form很相似,但是却比form更强大,下面体验一下。开始
安装:pip install django-rest-framework
创建一个新django项目:
django-admin.py startproject rest python manage.py startapp snippet
rest/settings.py添加app:
INSTALLED_APPS = ( ... 'rest_framework', 'snippets', )
创建一个model
snippet/models.py:
from django.db import models # Create your models here. LANGUAGE_CHOICES = ( ('1', 'cn'), ('2', 'us') ) STYLE_CHOICES = ( ('1', 't1'), ('2', 't2') ) 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= '1',max_length=5) style = models.CharField(choices=STYLE_CHOICES, default='1',max_length=5) class Meta: ordering = ('created',)
创建serializer.py文件:
snippet/serializer.py:
from rest_framework import serializers from snippet.models import Snippet,LANGUAGE_CHOICES,STYLE_CHOICES class Snippetserializer(serializers.Serializer): pk = serializers.IntegerField(read_only=True) title = serializers.CharField(required=False, allow_blank=True, max_length=32) code = serializers.CharField(style={'base_template': 'textarea.html'}) linenos = serializers.BooleanField(required=False) language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default= '1') style = serializers.ChoiceField(choices=STYLE_CHOICES, default='1') 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.language = validated_data.get('language', instance.language) instance.style = validated_data.get('style', instance.style) instance.save() return instance
创建表结构:
python manage.py makemigrations python manage.py migrate
开始使用django命令行,写一些序列化测试代码:
$ python manage.py shell >>> from snippet.models import Snippet >>> from snippet.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() >>>> obj = Snippetserializer(snippet) >>> obj.data {'language': '1', 'pk': 2, 'title': '', 'code': 'print"hello,world"\n', 'linenos': False, 'style': '1'} >>> obj['code'] <BoundField value=print"hello,world" errors=None> >>> content=JSONRenderer().render(obj.data) >>> stream = BytesIO(content) >>> content1 = JSONParser().parse(stream) >>> content2=JSONRenderer().render(obj.data).decode() >>> print(content) b'{"pk":2,"title":"","code":"print\\"hello,world\\"\\n","linenos":false,"language":"1","style":"1"}' >>> type(obj) <class 'snippet.serializers.Snippetserializer'> >>> type(obj.data) <class 'rest_framework.utils.serializer_helpers.ReturnDict'> >>> type(content) <class 'bytes'> >>> type(stream) <class '_io.BytesIO'> >>> content2=JSONRenderer().render(obj.data).decode() >>> type(content1) <class 'dict'> >>> type(content2) <class 'str'> >>> type(json.loads(content2)) <class 'dict'> #可以看到,由rest serializer处理后的model对象变成了其的serializer对象,使用obj.data方法可以取出其内容,然后使用jsonrender方法将数据渲染成byte格式的json字符串,可以再通过bytesIO转换和通过jsonparser方法转换回dict格式。也可以直接在jsonrender的时候使用decode()方法处理,直接返回json格式str,然后通过json.loads()方法反序列化成dict格式。
同时,作为为django量身定制的框架,serializer也支持queryset的序列化(原生json模块不支持序列化queryset),在序列化的时候添加一个many = True参数即可:
>>> serializer= Snippetserializer(Snippet.objects.all(),many=True) >>> serializer.data [OrderedDict([('pk', 1), ('title', ''), ('code', 'foo="bar"\n'), ('linenos', False), ('language', '1'), ('style', '1')]), OrderedDict([('pk', 2), ('title', ''), ('code', 'print"hello,world"\n'), ('linenos', False), ('language', '1'), ('style', '1')])] >>> serializer.data[0] OrderedDict([('pk', 1), ('title', ''), ('code', 'foo="bar"\n'), ('linenos', False), ('language', '1'), ('style', '1')]) >>> serializer.data[0]['code'] 'foo="bar"\n'
梳理一下:
1.model对象通过serializer方法序列化成新的对象obj,obj.data可以取出此对象的各items
2.jsonrender方法可以将obj.data渲染成byte格式对象,再通过byteIO处理可以转换成python的byte格式数据流。也可以decode成json风格str类型。
3.jsonparser方法可以将数据流(json风格str)反处理成dict格式
ModelSerializer
如modelform一样,restframework同样存在可以直接基于model关联,进行field字段关联验证等功能的模块,ModelSerializer.改写snippet/serializer.py:
from rest_framework import serializers from snippet.models import Snippet class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id','title','code','linenos','language','style')
写一个视图views.py,提供list查询、提交,单个对象查询、修改、删除方法:
from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser from snippet.models import Snippet from snippet.serializers import SnippetSerializer class JSONResponse(HttpResponse): def __init__(self,data,**kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'application/json' super(JSONResponse,self).__init__(content,**kwargs) @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) return JSONResponse(serializer.data) elif request.method == 'POST': data = JSONParser().parse(request) serializer = SnippetSerializer(data=data) 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) 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) 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)
定义urls规则关联视图函数:
urls.py:
from django.conf.urls import url from django.contrib import admin from snippet a025 import views as snippet_views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^snippets/$',snippet_views.snippet_list), url(r'^snippets/detail/(?P<pk>[0-9]+)/$', snippet_views.snippet_detail), ]
验证测试:
开启服务:
python manage.py runserver
测试:
$ curl http://127.0.0.1:8000/snippets/ [{"id":1,"title":"","code":"foo=\"bar\"\n","linenos":false,"language":"1","style":"1"},{"id":2,"title":"","code":"print\"hello,world\"\n","linenos":false,"language":"1","style":"1"}]ywq@ywq-ThinkPad-E470:/usr/local/myutils$ curl http://127.0.0.1:8000/snippets/detail/1 $ curl http://127.0.0.1:8000/snippets/detail/1/ {"id":1,"title":"","code":"foo=\"bar\"\n","linenos":false,"language":"1","style":"1"}
简单的接口OK了
相关文章推荐
- Django 之REST framework学习1:Serialization(序列化)
- Django 之REST framework学习:序列化的几种方式
- Django serializers 序列化 rest_framework
- django-rest-framework指南(1):序列化
- Django序列化神器插件rest-framework
- django-rest-framework笔记-序列化篇
- django-rest-framework序列化的使用(一)
- django restframework 序列化
- python3-开发进阶Django中序列化以及rest_framework的序列化
- Django-Rest-Framework 教程: 1. 序列化 (Serialization)
- django rest framework 入门1-序列化 Serialization
- django-rest-framework之序列化
- Django REST framework+Vue 打造生鲜超市(三)
- Django REST framework+Vue 打造生鲜超市(五)
- 【Django】 rest-framework和RestfulAPI的设计
- Django 之REST framework学习3:CBV
- Django 之REST framework学习5:关联性和超链接API(Relationships & Hyperlinked APIs)
- Django Rest Framework - 异常 、返回值处理 与 分页实现
- Django Restframework 实践(二)
- django-rest-framework 使用例子