二.drf之使用序列化编写视图
总结:两功能
序列化:
a.拿到queryset --->idc = Idc.objects.all()
b.将queryset给序列化成类---->serializer = IdcSerializer(idc, many=True)
c.转json: --->content = JSONRenderer().render(serializer.data)用序列化类的data属性可以输出所有的数据是一个字典的,并转成json字符串
反序列化:
a.将字符串content转成流--->stream = BytesIO(content)
b.将流转成序列化的数据字典--->data = JSONParser().parse(stream)
c.将字典反序列化 -->serializer = IdcSerializer(data=data)
d.验证并保存 --->serializer.is_valid() -->serializer.save()
一.应用示例
需求:把用户列表用带分页功能的展示出来。使用:视图函数+序列化类将Idc表列表取出来返回json数据。
需求分析:两个视图函数
def idc_list():
get方法:
返回所有记录
post方法:
创建一条记录
def idc_detail(pk):
get方法:
返回指定(pk对应的)记录
put方法:
修改指定记录
delete方法:
删除这条记录
1.get请求方法:
(1)views.py:
from django.shortcuts import render
from django.http import HttpResponse
from .models import Idc
from .serializers import IdcSerializer
from rest_framework.renderers import JSONRenderer
def idc_list(request, *args, **kwargs):#接收request,位置,关键字参数
if request.method == "GET":
queryset = Idc.objects.all()
serializer = IdcSerializer(queryset, many=True)
content = JSONRenderer().render(serializer.data)
return HttpResponse(content, content_type="application/json")
elif request.method == "POST":
pass
return HttpResponse("")
(2)apps/idcs/urls.py:
from django.conf.urls import url
from .views import idc_list
urlpatterns = [
url(r"^idcs/$",idc_list)
]
(3)devops/urls.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include("idcs.urls"))
]
(python36env) [vagrant@CentOS7 devops]$ python manage.py runserver 0.0.0.8000 启动后效果如下
2.编写POST--
注意这里POST想要的数据不是request.POST的数据,drf提供了方案:它可以从我们的requset对象里直接拿,直接把request传给它就可以了。
先django shell中测试下:
命令行测试方式:
(1)(python36env) [vagrant@CentOS7 ~]$ pip install httpie 安装http
(2)(python36env) [vagrant@CentOS7 ~]$ http --json POST http://127.0.0.1:8000/idcs/ aaa=bbb bbb=ccc
HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sat, 06 Jun 2020 03:34:25 GMT
Server: WSGIServer/0.2 CPython/3.6.6
X-Frame-Options: SAMEORIGIN
此时就能接收到数据如下:
(3)#python manage.py runserver 0.0.0.0:8000
[06/Jun/2020 03:33:36] "POST /idcs HTTP/1.1" 500 60032
{'aaa': 'bbb', 'bbb': 'ccc'}
或用postman软件测试: 在我们做前后端分离的项目的时候,这个工具测试后台接口还是非常便利的,如果我们想要在呼叫Web API时一并夹带JSON数据时就用它 (python36env) [vagrant@CentOS7 devops]$ python manage.py runserver 0.0.0.0:8000 执行就能收到提交的数据了
{'name': 'a昆明机房', 'address': '昆明a', 'phone': '', 'email': 'rock@51reboot.com', 'letter': 'kma'}
[06/Jun/2020 04:28:37] "POST /idcs/ HTTP/1.1" 200 0
views.py中:
from django.shortcuts import render
from django.http import HttpResponse
from .models import Idc
from .serializers import IdcSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser #重写JsonResponse类为自定义json--实现你传一data数据我帮你序列化:它其实就是把下面两函数中重复的代码(注释部分)封装到此
class JSONResponse(HttpResponse):
def __init__(self,data,**kwargs):
#指定为json
kwargs.setdefault('content_type', 'application/json')
#把data数据转换成json格式字符串
content = JSONRenderer().render(data)
#把字符串给httpresponse--super是执行父类的init方法
super(JSONResponse, self).__init__(content=content, **kwargs) def idc_list(request, *args, **kwargs):#接收request,位置,关键字参数
if request.method == "GET":
queryset = Idc.objects.all()
serializer = IdcSerializer(queryset, many=True)
return JSONResponse(serializer.data)
# content = JSONRenderer().render(serializer.data)
# return HttpResponse(content, content_type="application/json")
elif request.method == "POST":
#拿到json数据
data = JSONParser().parse(request)
#反序列化--把json数据给序列化类
serializer = IdcSerializer(data=data)
if serializer.is_valid():
serializer.save()
# content = JSONRenderer().render(serializer.data)
# return HttpResponse(content, JSONRenderer().render(serializer.data))
return JSONResponse(serializer.data)
return HttpResponse("")
此时命令行中也可直接测试并拿到数据:
(python36env) [vagrant@CentOS7 devops]$ http http://127.0.0.1:8000/idcs/ get请求
HTTP/1.1 200 OK
[
{
"address": "昆明",
"email": "rock@51reboot.com",
"id": 1,
"letter": "km",
"name": "昆明机房",
"phone": "1234568"
},
{
"address": "大理",
"email": "rock@51reboot.com",
"id": 2,
"letter": "dl",
"name": "大理机房"
3.编写idc_detail
(1)views.py中:
from django.shortcuts import render
from django.http import HttpResponse
from .models import Idc
from .serializers import IdcSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser #重写JsonResponse类为自定义json--实现你传一data数据我帮你序列化:它其实就是把下面两函数中重复的代码(注释部分)封装到此
class JSONResponse(HttpResponse):
def __init__(self,data,**kwargs):
#指定为json
kwargs.setdefault('content_type', 'application/json')
#把data数据转换成json格式字符串
content = JSONRenderer().render(data)
#把字符串给httpresponse--super是执行父类的init方法
super(JSONResponse, self).__init__(content=content, **kwargs) def idc_list(request, *args, **kwargs):#接收request,位置,关键字参数
if request.method == "GET":
queryset = Idc.objects.all()
serializer = IdcSerializer(queryset, many=True)
return JSONResponse(serializer.data)
# content = JSONRenderer().render(serializer.data)
# return HttpResponse(content, content_type="application/json")
elif request.method == "POST":
#拿到json数据
data = JSONParser().parse(request)
#反序列化--把json数据给序列化类
serializer = IdcSerializer(data=data)
if serializer.is_valid():
serializer.save()
# content = JSONRenderer().render(serializer.data)
# return HttpResponse(content, JSONRenderer().render(serializer.data))
return JSONResponse(serializer.data)
return HttpResponse("") def idc_detail(request, pk, *args, **kwargs):
#先获取pk--主键,可能会出错
try:
idc = Idc.objects.get(pk=pk)
#不存在则直接抛出404
except Idc.DoesNotExist:
return HttpResponse(satatus=404)
#如果有pk且请求方法是get那就直接给序列化
if request.method == "GET":
serializer = IdcSerializer(idc)
return JSONResponse(serializer.data)
#put表示修改
elif request.method == "PUT":
#拿到数据解析参数
content = JSONParser().parse(request)
#idc是原始数据,data是修改成什么样的数据
serializer = IdcSerializer(idc, data=content)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data)
return JSONResponse(serializer.errors, status=400)
elif request.method == "DELETE":
idc.delete()
#返回空
return HttpResponse(status=204)
(2)apps/idcs/urls.py:
from django.conf.urls import url
from .views import idc_list, idc_detail
urlpatterns = [
url(r"^idcs/$",idc_list),
url(r"^idcs/(?P<pk>[0-9]+)/$",idc_detail)
]
命令行测试中访问能拿到数据了:
(python36env) [vagrant@CentOS7 devops]$ http http://127.0.0.1:8000/idcs/1/ get请求
HTTP/1.1 200 OK
{
"address": "昆明",
"email": "rock@51reboot.com",
"id": 1,
"letter": "km",
"name": "昆明机房",
"phone": ""
}
如postman测试修改第一条记录:
(python36env) [vagrant@CentOS7 devops]$ http http://127.0.0.1:8000/idcs/1/ 终端验证改的结果
{
"address": "昆明",
"email": "rock@511111reboot.com", ---->改了
"id": 1,
"letter": "km",
"name": "昆明机房",
"phone": "1234568"
}
二.包装API,包装url,api_root
1.包装API:
用于基于函数视图的@api_view装饰器。
用于基于类视图的APIView类。
如下使用:
from rest_framework.decorators import api_view #导入装饰器api
from rest_framework import status #导入状态码
from rest_framework.response import Response
@api_view(["GET","POST"])
def idc_list_v2(requset, *args, **kwargs):
2.包装url:给我们的网址添加可选的格式后缀
http://127.0.0.1:8000/idcs.json
http://127.0.0.1:8000/idcs/2.json
urls.py中导入如下方法即可解决:
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = format_suffix_patterns(urlpatterns)
3.视图集
- REST框架包括一个用于处理ViewSets的抽象,它允许开发人员集中精力对API的状态和交互进行建模,并根据常规约定自动处理URL构造。
- ViewSet类与View类几乎相同,不同之处在于它们提供诸如read或update之类的操作,而不是get或put等方法处理程序。
- ViewSet类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个Router类来处理自己定义URL conf的复杂性。
4.使用路由器
因为我们使用的是ViewSet类而不是View类,我们实际上不需要自己设计URL。将资源连接到视图和url的约定可以使用Router类自动处理。我们需要做的就是使用路由器注册相应的视图集,然后让它执行其余操作。
5.视图(views)vs视图集(viewsets)之间的权衡
- 使用视图集可以是一个非常有用的抽象。它有助于确保URL约定在你的API中保持一致,最大限度地减少编写所需的代码量,让你能够专注于API提供的交互和表示,而不是URLconf的细节。
- 这并不意味着采用视图集总是正确的方法。在使用基于类的视图而不是基于函数的视图时,有一个类似的权衡要考虑。使用视图集不像单独构建视图那样明确。
二.drf之使用序列化编写视图的更多相关文章
- 经历了源码的痛苦,掌握DRF的核心序列化器
目录 DRF的核心--序列化器 序列化器 什么是序列化和反序列化? 序列化 序列化demo 字段类型 字段参数 序列化自定制返回字段 方法一:在序列化类(serializers.py)中写 方法二:在 ...
- DRF中的序列化器
DRF中的序列化器详细应用 视图的功能:说白了就是接收前端请求,进行数据处理 (这里的处理包括:如果前端是GET请求,则构造查询集,将结果返回,这个过程为序列化:如果前端是POST请求,假如要对数 ...
- Django基础--Django基本命令、路由配置系统(URLconf)、编写视图、Template、数据库与ORM
web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构. 使用框架可以帮你快速开发特定的系统. 简单地说,就是你用别人搭建好的舞台来做表演. 尝试搭建一个简单 ...
- day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能
目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...
- 使用Typescript重构axios(二十八)——自定义序列化请求参数
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- DTCMS插件的制作实例电子资源管理(二)Admin后台页面编写
总目录 插件目录结构(一) Admin后台页面编写(二) 前台模板页编写(三) URL重写(四) 本实例旨在以一个实际的项目中的例子来介绍如何在dtcms中制作插件,本系列文章非入门教程,部分逻辑实现 ...
- Django---手动编写视图
手动编写视图 一. Request----->URL---->业务处理(Views)(Http Response) Response-------> 二. VOE Django ...
- 二、Django用Eclipse编写一个登录界面
一.Django用Eclipse编写一个登录界面 二.Django用Eclipse编写一个登录界面Ajax和Django交互 各软件版本:Python 2.7.14,django 1.6.11 原来已 ...
- 【DRF框架】序列化组件
DRF框架的序列化组件 在前后端分离的应用模式中,后端仅返回前端所需的数据,返回的数据类似是JSON,因此需要使用序列化组件进行序列化再将数据返回 使用JsonResponse做序列化 # 使用Js ...
随机推荐
- Java实现 蓝桥杯VIP 算法训练 数组查找及替换问题
描述 给定某整数数组和某一整数b.要求删除数组中可以被b整除的所有元素,同时将该数组各元素按从小到大排序.如果数组元素数值在A到Z的ASCII之间,替换为对应字母.元素个数不超过100,b在1至100 ...
- Java实现 LeetCode 6 Z字形变换
6. Z 字形变换 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L ...
- java实现 蓝桥杯 算法提高 盾神与条状项链
问题描述 有一天,盾神捡到了好多好多五颜六色的珠子!他心想这些珠子这么漂亮,可以做成一条项链然后送给他心仪的女生~于是他用其中一些珠子做成了长度为n的项链.当他准备把项链首尾相接的时候,土方进来了. ...
- 用struts的action运行jsp页面
struts是开源框架.使用Struts的目的是为了帮助我们减少在运用MVC设计模型来开发Web应用的时间.如果我们想混合使用Servlets和JSP的优点来建立可扩展的应用,struts是一个不错的 ...
- Jmeter环境部署
一.安装jdk 下载jdk 双击jdk-8u211-windows-x64.exe,默认下一步安装 我的电脑-属性-高级系统设置-环境变量 在“系统变量”出,新建”JAVA_HOME”,配置jdk的安 ...
- 如何在Vim中的查找替换
“%s/最/第二/g” 用vim的人都知道,这是把所有“最”替换成“第二”的意思.其实vim的查找替换功能非常强大,用的好可以极大提升效率. vim的查找替换命令如下所示: :{作用范围}s/{ ...
- <WP8开发学习笔记>获取手机的常用型号(如Lumia920,而非RM-822)
之前WP7时代可以用API获得WP手机的型号如lumia510,但是到了WP8后用APi只能获得硬件版本号了如RM-822,这种型号可以让我们更详细的了解具体的硬件版本,比如国行和港行,设备版本号不一 ...
- CentOS Linux release 7.7.1908 (Core)--rabbitmq安装
1.连接服务器,输入账号和密码,密码输入的时候是看不见的,只管输就行,然后回车. 2.安装Erlang,RabbitMQ是用这门语言写的,所以要安装他. 3.安装filezilia就是win和linu ...
- 使用LaTeX输入矩阵
当前各种文本编辑器支持的LaTeX数学公式库大多基于KaTeX,或者在Web中用MathJax的比较多,下面给出一种在Web中输入矩阵的例子 $$\left[ \begin{array}{cccc}a ...
- cb43a_c++_STL_算法_删除_(1)remove_remove_if
cb43a_c++_STL_算法_删除_(1)remove_remove_ifremove()remove_if() 注意:1.并不是真正的删除,而是把后面的元素向前移动,覆盖被删除元素,元素个数并没 ...