REST-framework快速构建API--初体验
一、快速上手
1、环境准备
安装restframework,注册app
pip install djangorestframework
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework',
]
2、url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publish/', views.PublishView.as_view()),
]
3、models
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from django.db import models # Create your models here.
from django.db import models # Create your models here. class Book(models.Model):
title=models.CharField(max_length=32)
price=models.IntegerField()
pub_date=models.DateField()
publish=models.ForeignKey("Publish")
authors=models.ManyToManyField("Author")
def __str__(self):
return self.title class Publish(models.Model):
name=models.CharField(max_length=32)
email=models.EmailField()
def __str__(self):
return self.name class Author(models.Model):
name=models.CharField(max_length=32)
age=models.IntegerField()
def __str__(self):
return self.name
4、views
基于CBV方式
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from django.shortcuts import render,HttpResponse # Create your views here.
from .models import Publish
from rest_framework.views import APIView class PublishView(APIView):
def get(self,request): #序列化方式4rest_framework
from rest_framework.response import Response
publish_list = Publish.objects.all()
ps = PublishSerializers(publish_list, many=True)
return Response(ps.data) def post(self,request):
return HttpResponse('POST')
5、测试

二、结果序列化
API返回结果的形式,json是非常流行的。但是我们在序列化结果时,有多种方式,每种方式实现的方式不同。
1、原生json方式
import json
publish_list = list(Publish.objects.all().values())
return HttpResponse(json.dumps(publish_list))
使用json方式对结果进行强转,先把结果强转成列表的方式,然后通过json的dumps方式对结果进行格式化。
注意:
这种方式实现最简单,也可以自定制需要返回的字段,通过在values中填写自己需要的字段即可。
2、model_to_dict方法
#序列化方式2
# from django.forms.models import model_to_dict
# publish_list = Publish.objects.all()
# data = []
# for obj in publish_list:
# data.append(model_to_dict(obj))
# return HttpResponse(data)
通过models自带的model_to_dict方法直接把obj对象转换成字典的形式,然后返回。缺点:需要把每个对象再次进行处理。
3、django自带的serializers方法
#序列化方式3
# from django.core import serializers
# publish_list = Publish.objects.all()
# data = serializers.serialize("json", publish_list)
# return HttpResponse(data)
三、基于REST-framework序列化
from rest_framework import serializers
class PublishSerializers(serializers.Serializer):
name=serializers.CharField(max_length=32)
email=serializers.CharField() from rest_framework.views import APIView
视图函数继承APIView方法
#序列化方式4rest_framework
from rest_framework.response import Response
publish_list = Publish.objects.all()
ps = PublishSerializers(publish_list, many=True)
return Response(ps.data)
既然有了前面三种方法,为什么这里还要用restframework的第四种方法呢?原因如下:
a、对于表结构复杂的情况,前面三种没有涉及到,需要我们自己去通过写逻辑代码实现;
b、对于我们需要的返回表结构中字段的结果,定制也是个问题,比如,我们的api只需要返回指定的几个字段;
c、对于我们后面对资源的操作,比如POST动作,需要对结果进行保存,是不是我们每次都需要自己写create方法去保存结果呢?
d、对于错误的处理;
等等.....诸如此类的需要考虑的问题,rest-framework都帮我们写好了逻辑,只需要我们去调用即可。
对于复杂表结构
from rest_framework import serializers class BookSerializers(serializers.Serializer):
title=serializers.CharField(max_length=32)
price=serializers.IntegerField()
pub_date=serializers.DateField()
#一对多,可以通过source指定列名,默认为str或unicode方法显示的
publish=serializers.CharField(source="publish.name")
#对于多对多我们可以自定义get_field方法,将object添加进去
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for author in obj.authors.all():
temp.append(author.name)
return temp
class BookViewSet(APIView):
def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
bs=BookSerializers(book_list,many=True)
return Response(bs.data)
注意:这里的many=True,表示对queryset进行操作,默认为对model对象进行操作。
四、使用ModelSerializer
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
depth=1
保存数据:
def post(self,request,*args,**kwargs):
bs=BookSerializers(data=request.data,many=False)
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
通过ModelSerializer方法,类似ModelForm方法,我们可以通过Meta类直接指定Model、fields,就能满足我们的需求。操作哪个表,提交哪些字段。save方法其实后端是调用的create方法,将我们提交的数据进行保存。
注意:
在BookSerializers里面,我们同样可以自定义返回多对多或一对多字段内容;
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
depth=1
publish=serializers.CharField(source="publish.name")
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for author in obj.authors.all():
temp.append(author.name)
return temp
但是这里如果使用ModelSerializer方法,使用save方法时,ModelSerializer默认自带的create方法不支持多对多的保存,需要我们重载create方法:
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
# exclude = ['authors',]
# depth=1
def create(self, validated_data):
authors = validated_data.pop('authors')
obj = Book.objects.create(**validated_data)
obj.authors.add(*authors)
return obj
五、单条数据操作
针对单条数据进行操作,比如books/1(GET/PUT/DELETE)
class BookDetailViewSet(APIView):
def get(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj)
return Response(bs.data)
def put(self,request,pk):
book_obj=c
bs=BookSerializers(book_obj,data=request.data)
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
def delete(self,request,pk):
Book.objects.filter(pk=pk).delete()
return Response()
注意:
put进行更新数据时,需要把单条数据的每个字段写全,即使之前已经是完整的一条记录,否则会报错。
六、超链接API
class BookSerializers(serializers.ModelSerializer):
publish= serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk")
class Meta:
model=Book
fields="__all__"
#depth=1
urls
urlpatterns = [
url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]
注意:
1、反向解析,通过name进行命名,这个代表前面的URL,不管pk怎么变化都可以引用;
2、view_name为反向解析的name,lookup_field为对应的哪个字段,这里的pk对应的是Model里面的id字段;
3、lookup_url_kwarg是命名url里面的分组关键字;
4、需要在views函数里面新增一个context={'request':request}
class BookView(APIView):
def get(self,request):
book_list=Book.objects.all()
bs=BookModelSerializers(book_list,many=True,context={'request': request})
return Response(bs.data)
def post(self,request):
# post请求的数据
bs=BookModelSerializers(data=request.data)
if bs.is_valid():
print(bs.validated_data)
bs.save()# create方法
return Response(bs.data)
else:
return Response(bs.errors)

注意:这里有一个问题,使用超链接post数据的时候,会有一个报错:

需要去掉超链接的配置才能POST数据,这里还没找到解决办法。
REST-framework快速构建API--初体验的更多相关文章
- 5分钟APIG实战: 使用Rust语言快速构建API能力开放
序言:Rust语言简介 参与过C/C++大型项目的同学可能都经历过因为Null Pointer.Memory Leak等问题“被” 加班了不知道多少个晚上.别沮丧,你不是一个人,Mozilla Fir ...
- Hbase王国游记之:Hbase客户端API初体验
§历史回顾 2018年岁末,李大胖朦胧中上了开往Hbase王国的车,伴着一声长鸣,列出缓缓驶出站台,奔向无垠的广袤. (图片来自于网络) 如不熟悉剧情的,可观看文章: 五分钟轻松了解Hbase列式存储 ...
- net core 微服务 快速开发框架 Viper 初体验2020-10-17
1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...
- web api 初体验之 GET和POST传参
上一篇我们讲到了web api跨域的问题 它几乎是每一个用web api的人都需要去解决的问题,不然都没法测试.接下来会遇到的问题就是传参了.还是用js前台调用服务的方式. GET 方式 get方式传 ...
- web api 初体验 解决js调用跨域问题
跨域界定 常见跨域: 同IP不同端口: http:IP:8001/api/user http:IP:8002/api/user 不同IP不同端口: http://172.28.20.100:8 ...
- Kong Api 初体验
请查看原文: https://www.fangzhipeng.com/nginx/kong/2016/07/11/kong-api-gateway/ Kong是一个可扩展的开源API层(也称为API网 ...
- Django Rest Framework 教程及API向导
Django Rest Framework 教程及API向导. 一.请求(Request)REST_FRAMEWORK 中的 Request 扩展了标准的HttpRequest,为 REST_FRAM ...
- .NET Core初体验 在window上构建第一个app
ASP.NET Core 是一个跨平台,高性能的开源框架,用于构建现代化的,基于云的互联网应用程序.使用 ASP.NET Core ,您可以: 构建Web应用程序和服务,IoT应用程序和移动后端. 在 ...
- gulp快速入门&初体验
前言 一句话先 gulp 是一个可以简单和自动化"管理"前端文件的构建工具 先说我以前的主要工作,我主要是做游戏服务端的,用c++/python,所以我对东西的概念理解难免要套到自 ...
- 快速构建第三方api应用
1.使用框架和扩展 详细请看composer.json "php": "^7.1.3", "laravel-admin-ext/config" ...
随机推荐
- 关于npm run build打包后css样式中的图片失效的问题(如background)
平时run dev都能正常显示的css背景图片在npm run build打包后竟然不显示了(写在标签对中的图片都可以正常显示),而且dist/static/img目录下是确实有这张图片的,于是查看打 ...
- 使用Python+opencv2时的文件命名及路径问题
最近在做一个数字图像的小项目,在最后的界面与程序结合阶段总是出现单个程序可以运行,但是使用界面传递的参数就运行不了的情况.在网上查了很多相关错误,最终确定是文件命名问题. 错误如下: cv2.erro ...
- 阿里八八Alpha阶段Scrum(4/12)
今日进度 叶文滔: 整合了一下已完成的界面设计,修复了一些BUG. 问题困难:制作多级悬浮按钮阻碍重重,首先是刚更新不久的Andriod Studio 3.0向前兼容性差,一些语句规则的修改无所适从, ...
- 很不错的关于依赖注入和AOP的系列文章
http://blog.csdn.net/tittop/article/details/6716033
- saltstack二次开发(二)
Saltstack的api Salt-api有两种方式,一种是函数的形式,有人家定义好的函数,我们可以直接调用,直接写python代码调用函数或者类就可以了.第二种形式是salt-api有封装好的ht ...
- JVM系列三:JVM参数设置
JVM系列三:JVM参数设置.分析 不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM.GC的参数,可以极大的减少由于GC工作,而导致的程序运 ...
- 有crontab中的脚本不执行,需要在脚本里面export各种环境变量
[oracle@sta ~]$ vi .bash_profile # .bash_profile # Get the aliases and functionsif [ -f ~/.bashrc ]; ...
- [转]改善C#程序的建议4:C#中标准Dispose模式的实现
需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...
- DFT scan chain
现代集成电路的制造工艺越来越先进,但是在生产过程中的制造缺陷也越来越难以控制,甚至一颗小小的PM2.5就可能导致芯片报废,为了能有效的检测出生产中出现的废片,需要用到扫描链测试(scan chain) ...
- Android 写一个Activity之间来回跳转的全局工具类(主要是想实现代码的复用)
废话不多说了,直接上代码,相信大家都能看得懂的. 一.主要工具类 package com.yw.chat.utils; import android.app.Activity; import andr ...