APIView基本使用

# drf是什么?
是一个第三方的app(需要在settings中注册),只能在djagno上使用 # APIView
安装了drf后,就可以导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类。(之前写视图类是继承django的View类) # 示例
接下来使用APIView写获取所有图书的接口

使用原生Django写接口(View + JsonResponse)

建表:

继承Django View写视图类:

这里可以使用JsonResponce进行序列化吗?

不能。JsonResponse只能序列化一些基础的数据类型如字典、列表。queryset对象不能直接进行序列化,只能通过for循环一个个拼成列表套字典的形式。

视图类路由配置:记得as_views()加括号

但是这样还是会报错:

查看源码:

可知我们上传的不是字典时,会报错。所以我们进行修改:

为了使返回给浏览器的json字符串可以显示中文,还需要加一个参数:(不处理也没事,只是便于查看)

代码:

class BookView(View):
def get(self, request):
print(type(request))
book_list = Book.objects.all()
# book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False}) # 只能序列化字典和列表,

使用drf写接口(APIView + drf Response)

模块导入:

# 不要忘了注册rest_framework这个app

from rest_framework.views import APIView
from rest_framework.response import Response '''
drf 帮我们封装了请求类、响应类、路由类、视图类
模块导入的时候很规范,比较好找
'''

drf 两种导入View的方式

APIView继承自django的View:



两种导入View的方式:

from django.views.generic import View  # View真正的位置
from django.views import View # 通过导包的方式导入View
'''
备注:导入包会执行包内的__init__文件。
'''

drf Response

在原有代码的基础上做改动,修改JsonResponse为drf的Response:

drf的response不仅可以序列化字典列表,还可以序列化字符串。

但是这样修改之后运行程序会报错:模板不存在

这很奇怪,我们一直都是编写视图,都没有用到模板,怎么会报错呢?但是使用postman访问我们的接口,是没有问题的。

问题解决:

注册drf app之后访问图书查询接口:

注册drf app之后用浏览器访问,可以显示一个好看的页面,包括js代码,而不仅仅是json格式的数据。

代码:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request class BookView(APIView): # APIView继承自django的View
def get(self, request):
# print(type(self.request)) # 新的request
# print(type(request))
print(request._request)
print(type(request._request)) #django.core.handlers.wsgi.WSGIRequest # print(request.method) # get
# print(request.path) # /books/
# print(request.GET) # 原来的get请求提交的参数
# print(request.POST) # 原来post请求提交的参数 book_list = Book.objects.all()
# book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return Response(res_list)

APIView源码分析

详细见上一篇博客...

# 视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程

# 一旦继承了APIView入口
-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
@classmethod
def as_view(cls, **initkwargs):
# 又调用了父类(View)的as_view
view = super().as_view(**initkwargs)
'''
# 从此以后,所有的请求都没有csrf的校验了
# 在函数上加装饰器
@csrf_exempt
def index(request):
pass
本质等同于 index=csrf_exempt(index)
'''
return csrf_exempt(view) -请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证),
-真正的执行,执行self.dispatch---->APIView的dispatch 【这是重点】
def dispatch(self, request, *args, **kwargs):
# 参数的request是原来的django原生的request
# 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
request = self.initialize_request(request, *args, **kwargs)
# self 是视图类的对象,视图类对象.request=request 新的request
self.request = request
try:
# 执行了认证,频率,权限 [不读]
self.initial(request, *args, **kwargs)
# 原来的View的dispatch的东西
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
# 如果出了异常,捕获异常,处理异常,正常返回
# 在执行三大认证和视图类中方法过程中,如果出了异常,是能被捕获并处理的---》全局异常的处理
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response # 总结:
1 只要继承APIView都没有csrf的认证了
2 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
3 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

Request类源码分析

详细见上一篇博客...

#1  视图类中使用的request对象,已经变成了drf提供的Request类的对象了
-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
-drf的request是这个类的对象:rest_framework.request.Request #2 request已经不是原来的request了,还能像原来的request一样使用吗?
-用起来,像之前一样
print(request.method) # get
print(request.path) # /books/
print(request.GET) # 原来的get请求提交的参数
print(request.POST) # 原来post请求提交的参数 #3 Request的源码分析:rest_framework.request.Request
-类中有个魔法方法:__getattr__ 对象.属性,属性不存在会触发它的执行
def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
try:
#反射:根据字符串获取属性或方法,self._request 是原来的request
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr) -以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的) -新的request内部有个老的request,就是 request._request -data 是个方法,被property装饰了,变成了数据属性用
-以后body体中提交的数据,都从这里取(request.POST)
-urlencoded,form-data:提交的数据在request.POST中
-json格式提交的数据,在requets.POST中没有,它在request.body中
-现在无论那种格式,都从request.data中取
-query_params:get请求提交的参数,等同于request._request.GET 或 request.GET
-其他:取文件也是从request.FILES中取,跟之前一样 # 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,需要拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据 # request.data 有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典 # 4 什么是魔法方法?
1 在类中只要以__开头,__结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 你学过的: __init__,__str__,__call__,......

drf request.data

当用户上传文件时,原生django的request不允许你print(request.body):

原因:如果用户传5个G的文件,当文件太大时无法打印。

使用drf的request,无论任何编码格式,都可以进行打印操作:

form-data、urlencode格式:



上传Json格式数据:

注意:request.data的结果是python字典,而不是querydict。

FBV实现request.data方法(练习)

练习:写一个装饰器装饰FBV,只要一装饰,该视图函数中的request就会有request.data这个方法。无论发送到后端的数据是哪种编码格式,这个request.data里面都有数据。

实现逻辑:

1.如果传入json:
从request.body中将json数据取出,再使用json.loads反序列化转成字典赋值给request.data.
2.如果是urlencoded或form-data格式:
直接把request.data = request.POST '''如何判断传入后端数据的编码格式?'''

序列化组件介绍

# 序列化组件介绍
是drf提供了一种可以快速实现序列化的类:序列化类
我们也可以继承它,写自己的类。
使用方式类似form组件。 # 用途
用来序列化queryset查询集合或单个对象的 # 原来的序列化方式
写一个获取所有图书接口 ---> 查询得到qs,单个book对象--->使用for循环,取出数据拼接成列表套字典--->转成json格式字符串,给前端 ---> 序列化 # 序列化组件与form组件对比 (重要)
form类中写属性 ---> 对类中出现的属性进行校验
serializer类中写属性 ---> 对类中出现的属性进行序列化 '''
serializer类中写到的属性 --对应--> 数据库中某字段,只有这些字段才会被序列化(类似form组件)
其他字段将不会出现在序列化对象的data方法中
'''

序列化类中只有name属性时,查询所有图书的结果:只会对name字段进行序列化。

有三个属性时,查询所有图书:

定义一个序列化类

首先需要在app下,新建一个py文件,我们将其命名为serializer:

然后需要继承drf写好的序列化类。

注意继承的方式,这么写是因为类中还要使用序列化组件中的字段类。

# 写序列化类:给book进行序列化
# from rest_framework.serializers import Serializer
from rest_framework import serializers class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类CharField
# 这个CharField和model层、form组件的CharField不是一个东西。
# price = serializers.CharField()
publish = serializers.CharField()

序列化类的使用

序列化多条数据

原来的代码:

修改原来的BookView的代码,将for循环的部分替代掉,让序列化类帮助我们处理数据:

class BookView(APIView):  # APIView继承自django的View
def get(self, request):
book_list = Book.objects.all()
# instance表示要序列化的数据,many=True表示序列化多条(如果instance是qs对象,一定要传many=True)
ser = BookSerializer(instance=book_list, many=True) return Response(ser.data) # 使用drf response '''instance:对象'''

这个instance参数可以传入queryset查询集(多个对象),也可以传入first取出来的单个对象。

当instance传入单个书籍对象时,可以不写many=True(默认情况many=False),

当传入queryset对象时,一定要传many=True

序列化单条数据

由于获取单条数据、多条数据都使用的是get请求,所以都是执行我们视图类中的一个get方法。两个不同的业务,都使用一个类中函数来处理,不太合适,有点臃肿:

所以我们选择新创建一个视图类,来实现查询一条数据的需求:

# 查询单条数据时的路由:/book/1/
class BookDetailView(APIView):
def get(self, request, pk): # 有名分组传入pk
book = Book.objects.filter(pk=pk).first() # 获取book对象
ser = BookSerializer(instance=book) # 无需 many=True
return Response(ser.data)

修改路由层:

反序列化

# 反序列化
后端发送给前端 ---> 序列化
前端发送给后端 ---> 反序列化 # 涉及序列化的操作
新增,修改---》前端传入的数据,要校验---》序列化类有数据校验功能 '''删除不涉及到序列化'''

新增数据

class BookView(APIView):  # APIView继承自django的View
def post(self, request):
# 前端传递数据,从request.data取出来
ser = BookSerializer(data=request.data)
if ser.is_valid(): # 表示校验前端传入的数据 没有写校验规则,现在等于没校验
ser.save() # 再写东西,这里会报错 调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
return Response(ser.data)
else:
return Response(ser.errors)

新增数据基本流程

前端传入的数据在request.data里:

通过双星号解包使用create方法新增数据。但是这样是有问题的,因为没有进行数据校验,不知道前端传入的数据是否合法。

此时可以选择form组件进行校验,但是序列化组件也有校验功能。

将前端输入传入序列化类的data参数,实例化出一个对象:

序列化对象也有is_valid方法(这里我们没有写校验规则,只是走一下流程):

校验通过进行保存。

依据resful规范,新增数据时,要返回新增的数据对象:

所以校验成功时,应该返回新增的对象;不成功时,返回错误信息。

序列化对象save方法报错

使用postman发送POST请求:

会产生报错:



提示create方法需要被重写(implemented)。

问题的原因:序列化对象的save方法

由于我们写的BookSerializer中没有save方法,所以会去父类serializers找save方法。

save方法中看这一部分代码:



由于我们是发送POST请求,所以序列化对象中没有instance这个属性(get请求中有instance属性,post请求有data属性),所以这里会执行self.create

又因为我们的BookSerializer中没有create方法,故又去父类找:



父类的create方法会直接抛出异常,提醒你重写create方法。

所以执行序列化对象.save()会报错。

重写序列化类create方法

在自己的序列化类重写create方法:

这里需要注意的是,要将新增的书籍对象给返回出来:

否则会触发断言。

代码:

class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类
price = serializers.CharField()
publish = serializers.CharField() # 重写create方法,
def create(self, validated_data):
res = Book.objects.create(**validated_data)
return res

修改数据

视图类:

# /book/1/ 修改主键为1的书籍
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
# 前端传递数据,从request.data取出来
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid(): # 表示校验前端传入的数据 没有写校验规则,现在等于没校验
ser.save() # 再写东西,这里会报错 调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
return Response(ser.data)
else:
return Response(ser.errors)

修改数据使用put请求访问路由book/1/

修改数据需要给序列化类传入两个参数:instance、data

也就是用前端传入的数据,修改后端查询到的数据。

这里序列化类的save方法也会报错,原因是:

当instance有值时,会执行序列化对象的update方法,这个方法也需要我们在序列化类中重写。

重写序列化类updata方法

class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类
price = serializers.CharField()
publish = serializers.CharField() # 重写 update
def update(self, instance, validated_data):
# instance 要修改的对象(传入的queryset\模型对象)
# validated_data 校验过后的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save()
return instance

这里需要注意的是:

  1. 需要调用save方法,将instance对象中的数据,存储到数据库。
  2. 需要将instance对象返回出去,否则会触发断言。

    (resful规范:修改之后,将修改成功的对象返回)

删除数据

直接在CBV中添加delete方法:

依据resful规范:删除数据应该返回一个空文档,所以这里返回一个Response()

练习

1 继承apiview写5个接口
2 fbv写个装饰器,装饰在视图函数,只要一装饰,以后的request就可以使用request.data,这个data无论是那种编码格式,都有数据

FBV添加装饰器实现request.data

需求:

# 1.
写个装饰器,装饰视图函数。
视图函数中得request就会有data属性,data属性中无论是urlencoded,form-data,json格式,里面都是body中提交的数据。

未加装饰器时,request没有data属性:

语法糖:python中的特殊语法。

特殊在语法糖只要放在一个函数上面,他就会把语法糖下面这个函数当做参数传入到装饰器中,并且把返回值赋值给被装饰的函数。整个过程相当于index = outer(index),装饰完之后index存的是inner函数的内存地址。

且装饰完之后,inner函数内的代码不会执行,当调用index时,inner才会执行。

完成第一个目标:给request对象添加data属性

对于原生django的request对象:

  1. 前端传入urlencodedform-datarequest.POST有数据。

    注意:

    form-data针对普通的键值对,还是解析到request.POST中,而将文件解析到request.FILES中。

    编码格式相关:

    https://www.cnblogs.com/garyhtml/p/15980939.html

  2. 前端传入json格式时,数据在request.body(bytes类型)。

  3. 前端传入文件时,数据在request.FILES

根据不同的编码格式,使用request的不同方法获取用户上传数据:

python3.5及以下版本:

json.loads只能传入字符串,如果传入bytes类型,将会报错。

查看源码(python3.5以上):



可见loads方法支持str、bytes类型数据。

isinstanceissubclass:

# isinstance
传两个参数第一个是对象,第二个是类,用于判断对象是不是这个类的对象
# issubclass
传两个参数第一个是类,第二个是类,用于判断第一个类是不是第二个类的子类

可以发现:

# json.loads 转换bytes字符串时会报错
bytes_str = 'im str'.encode('utf8')
print(bytes_str) # b'im str'
try:
json.loads(bytes_str)
except:
print('error') # json.loads 转换bytes字典时 可直接转换
json_dict = json.dumps({'name': '猪猪侠', 'price': '198', 'publish': '王者出版社'})
bytes_dict = bytes(json_dict, 'gbk')
print(
bytes_dict) # b'{"name": "\\u732a\\u732a\\u4fa0", "price": "198", "publish": "\\u738b\\u8005\\u51fa\\u7248\\u793e"}'
decode_dict = json.loads(bytes_dict) # 使用urlencoded或form-data编码
# request.body会接受到 bytes字符串 --> b'im str'
# 此时json.loads会报错 # 使用raw 上传json格式
# request.body会接受到 bytes字典 --> b'{"name": "\\u732a\\u732a\\u4fa0"}
# 此时json.loads可以直接转换

使用异常捕获:

当编码格式是urlencodedform-data时,传入的数据是这种格式name=lqz&age=19

方法在python3.5以上只能支持传入strjson格式。

所以这种情况下会引发loads内部的异常,此时我们进行异常捕获,执行except下的代码,使用request.POST获取用户输入。

测试功能是否实现:

发送urlencoded:



发送form-data:



注意:form-data格式不能打印request.body。(因为form-data可能携带文件,而文件在request.body请求体中,文件太大可能无法打印,所以django直接禁止你打印)

发送json格式数据:



注意这里是python字典,而不是querydict。

CBV添加装饰器实现request.data

代码:

import json
from django.http import JsonResponse
from django.views import View
from .models import Book
from django.db import transaction # orm事务
from django.utils.decorators import method_decorator # 给CBV添加装饰器 def request_data(func): # 实现request.data
def inner(request, *args, **kwargs):
try:
request.data = json.loads(request.body) # 给loads方法传入bytes类型时会报错
except json.decoder.JSONDecodeError:
request.data = request.POST
res = func(request, *args, **kwargs)
return res
return inner class BookView(View):
@method_decorator(request_data)
def post(self, request):
"""
POST 新增对象:返回新生成的资源对象
{name:西游记,price:99}
"""
# 新增一个 只能使用urlencoded或form-data编码,使用json形式编码不行,因为json格式编码提交的数据,不能从request.POST中取,从body中获取
# 使用request.data
with transaction.atomic():
name = request.data.get('name')
price = request.data.get('price')
publish = request.data.get('publish')
Book.objects.create(name=name, price=price, publish=publish)
return JsonResponse({'name': name, 'price': price, 'publish': publish})

实现5个接口

需求:

# 2 实现5个接口
-使用APIVIew+Response+序列化类实现
-使用View+JsonResponse写5个接口

使用View+JsonResponse

视图类优化:

all方法不会一次性将数据读到内存复制给变量,而是在SQL使用了LIMIT语句。

查询所有数据:

当给Jsonresponse传入的不是字典时,会报错,需要加参数safe=False

新增一个:

注意返回新增的数据。

查询一个数据:



由于获取数据都是使用get方法,为了解耦合,所以要新建一个视图类。

修改一个数据:



注意使用save方法保存对象中的数据。

删除一个数据:



注意删除后,依据resful规范,返回一个空字典。

路由配置:

上面的修改数据的接口是有问题的:

put请求常见问题:使用request.POST只能获取post请求提交的数据,而不能获取put请求提交的数据。

所以需要修改数据时,我们不使用urlencoded编码格式,而是上传JSON格式。

使用postman发送put请求,想要发送json格式数据,可以勾选raw:

在后端使用request.body获取数据:

注意:如果使用put请求发送json格式以外的数据,loads方法将会报错。

代码:

import json

from django.shortcuts import render
from django.http import JsonResponse
from django.views import View
from .models import Book
from django.db import transaction
from django.db.models.query import QuerySet # def unpack() class BookView(View):
def get(self, request):
"""
GET 获取所有数据:返回资源对象的列表(数组)
[{name:红楼梦,price:99},{name:红楼梦,price:99},{name:红楼梦,price:99}]
"""
books = Book.objects.all()
book_list = [{'name': book.name, 'price': book.price, 'publish': book.publish} for book in books]
return JsonResponse(book_list, safe=False) def post(self, request):
"""
POST 新增对象:返回新生成的资源对象
{name:西游记,price:99}
"""
# 新增一个(只能使用urlencoded或form-data编码,使用json形式编码不行,因为json格式编码提交的数据,不能从request.POST中取,从body中)
name = request.POST.get('name')
price = request.POST.get('price')
publish = request.POST.get('publish')
Book.objects.create(name=name, price=price, publish=publish)
return JsonResponse({'name': name, 'price': price, 'publish': publish}) class BookDetailView(View):
def get(self, request, pk):
"""
GET 获取单个数据:返回单个资源对象
{name:红楼梦,price:99}
"""
book = Book.objects.filter(pk=pk).first()
return JsonResponse({'name': book.name, 'price': book.price, 'publish': book.publish}) def put(self, request, pk):
"""
PUT 修改一个对象:返回完整的资源对象
{name:西游记,price:100}
"""
# request.POST只能取post提交的urlencoded或form-data编码数据,put提交的取不到
user_dict = json.loads(request.body)
name = user_dict.get('name')
price = user_dict.get('price')
publish = user_dict.get('publish')
with transaction.atomic():
Book.objects.filter(pk=pk).update(name=name, price=price, publish=publish) return JsonResponse({'name': name, 'price': price, 'publish': publish}) def delete(self, request, pk):
"""
DELETE 删除:返回一个空文档
{}
"""
with transaction.atomic():
Book.objects.filter(pk=pk).delete()
return JsonResponse(data={})

使用原生django+反射

核心代码:

class BooksView(views.View):

    def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
book_obj = Book.objects.first()
self.file_list = [i for i in book_obj.__dict__ if not i.startswith('_')]
# 获取类中所有字段名,将其存入列表中。
# 类似 ['name','price','publish']

在django测试环境下查看Book.objects.first是什么:

import os

def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf01.settings')
import django
django.setup() from app01 import models
book_obj = models.Book.objects
book_obj_first = models.Book.objects.first()
print(book_obj, type(book_obj), book_obj.__dict__)
print(book_obj_first, type(book_obj_first), book_obj_first.__dict__) main()

可以使用__dict__获取类中所有字段名:

from .models import Book
from django import views
from django.http import JsonResponse
import json
from json import JSONDecodeError class BooksView(views.View): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
book_obj = Book.objects.first()
self.file_list = [i for i in book_obj.__dict__ if not i.startswith('_')] def get(self, request):
book_queryset = Book.objects.all()
book_list = []
for book in book_queryset:
book_list.append({book_file: getattr(book, book_file) for book_file in self.file_list})
return JsonResponse(book_list, safe=False, json_dumps_params={'ensure_ascii': False}) def post(self, request):
bank_data = {'code': 10000, "msg": '', "error": {}}
res_dict = {}
try:
book_data = request.POST if request.POST else json.loads(request.body)
except JSONDecodeError as e:
bank_data['msg'] = '什么都没写'
else:
# 删除字段 id
self.file_list.remove('id')
# 循环出所有字段
for book_file in self.file_list:
# 判断前端传过来的字段是否完整, 不完整则提示它字段为空
if not book_data.get(book_file):
bank_data['error'][book_file] = '字段%s为空' % book_file
else:
res_dict[book_file] = book_data.get(book_file)
# 判断字段时候有为空的 如果有不为空则添加
if not bank_data.get('error'):
Book.objects.create(**res_dict)
bank_data['data'] = res_dict
bank_data['msg'] = '添加成功'
else:
bank_data['code'] = 10001
bank_data['msg'] = '添加失败'
return JsonResponse(bank_data, json_dumps_params={'ensure_ascii': False}) class Books2View(views.View):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
book_obj = Book.objects.first()
self.file_list = [i for i in book_obj.__dict__ if not i.startswith('_')] def get(self, request, pk):
book_obj = Book.objects.filter(pk=pk).first()
data = {book_file: getattr(book_obj, book_file) for book_file in self.file_list}
return JsonResponse(data) def put(self, request, pk):
book_obj = Book.objects.filter(pk=pk).first()
# put 请求的POST和GET都取不到, 所以只能在body里面取
book_data = json.loads(request.body)
print(book_data)
for book_file in self.file_list:
setattr(book_obj, book_file, book_data.get(book_file, getattr(book_obj, book_file)))
book_obj.save()
print(book_obj.name)
data = {book_file: getattr(book_obj, book_file) for book_file in self.file_list}
return JsonResponse(data) def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return JsonResponse({})

前端:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'js_dir/jquery-1.12.4.js' %}"></script>
<script src="{% static 'js_dir/sweelalert.js' %}"></script>
</head>
<body>
<button id="btn1">普通数据</button>
<input type="file" id="file">
<button id="btn2">文件数据</button>
<button id="btn3">Json数据</button> <script>
$('#btn1').click(function () {
$.ajax({
url: '/aaa/',
type: 'post',
data: {"name": "jason"},
success: function (args) {
swal(args.msg)
}
})
})
$('#btn2').click(function () {
let formData = new FormData()
formData.append("file", $('#file')[0].files[0])
$.ajax({
url: '/aaa/',
type: 'post',
data: formData,
contentType: false,
processData: false,
success: function (args) {
swal(args.msg)
}
})
})
$('#btn3').click(function () {
$.ajax({
url: '/aaa/',
type: 'put',
data: JSON.stringify({"name": "jason"}),
contentType: "application/json",
success: function (args) {
swal(args.msg)
}
})
})
</script>
</body>
</html>

参考博客:https://www.cnblogs.com/zz1254/articles/17080928.html

drf-Response drf-request.data 序列化类的使用 反序列化新增、修改、删除数据的更多相关文章

  1. 【Django drf】 序列化类常用字段类和字段参数 定制序列化字段的两种方式 关系表外键字段的反序列化保存 序列化类继承ModelSerializer 反序列化数据校验源码分析

    目录 序列化类常用字段类和字段参数 常用字段类 常用字段参数 选项参数 通用参数 序列化类高级用法之source source填写类中字段 source填写模型类中方法 source支持跨表查询 定制 ...

  2. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  3. DRF提供的请求与响应类

    一 内容协商 drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个视图子类出来提供给我们使用. Dja ...

  4. DRF使用Serializer来进行序列化和反序列化操作

    在serlizers中添加 # -*- coding: utf-8 -*- from rest_framework import serializers from .models import * c ...

  5. Django drf:cbv源码、resful规范及接口、drf使用、response源码、序列化

    一.cbv源码分析 二.resful规范 三.django中写resful的借口 四.drf写resful的借口 五.APIVIew源码分析 六.drf之序列化 一.cbv源码分析 -CBV和FBV ...

  6. 使用drf的序列化类实现增删改查接口

    目录 什么是DRF 安装DRF 基于原生创建五个接口 基于rest_framework的增删改查 查询多条数据 流程 创建表 创建序列化类 创建视图类 增加路由 查询单条数据 序列化类不变 视图类定义 ...

  7. Django(45)drf序列化类的使用(Serializer)

    前言 上一篇文章我们讲述了序列化,这篇就带大家一起来实现以下序列化 Serializer 我们使用序列化类Serializer,我们来看下源码结构,这里推荐使用pycharm左边导航栏的Structu ...

  8. Django(46)drf序列化类的使用(ModelSerializer)

    前言 我们上篇文章使用到了Serializer类,可能有小伙伴说太过复杂,那么本篇就为大家带来更加简便的序列化类ModelSerializer ModelSerializer 先来看下ModelSer ...

  9. DRF(2) - 解析器,序列化组件使用(GET/POST接口设计)

    一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...

  10. drf03 drf视图中提供的请求类和响应类

    drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. Django REST ...

随机推荐

  1. 题解 CF690C2

    题目大意: 给你一棵树,求一下直径 题目分析: emm,怎么说吧,就是树的直径的裸板子. 可能有人不大理解,明明是图,你为什么要说是给定一棵树. 大家可以自行验证一下,满足如下两个性质的是否是一棵树: ...

  2. SpringBoot进阶教程(七十八)邮件服务

    Sun公司提供了JavaMail用来实现邮件发送,但是配置烦琐,Spring中提供了JavaMailSender用来简化邮件配置,Spring Boot则提供了MailSenderAutoConfig ...

  3. [ABC274D] Robot Arms 2

    Problem Statement You are given a sequence $A = (A_1, A_2, \dots, A_N)$ of length $N$ consisting of ...

  4. 图片Base64相互转换

    一.简介 Base64编码是一种广泛应用于网络传输和数据存储的编码方式.在实际应用中,我们将图片转换为Base64编码,可以大大减少数据量,便于传输和存储.本文将详细介绍图片Base64编码的相互转换 ...

  5. Windows下使用C#和32feet.NET开发蓝牙传输功能的记录

    引用的第三方Nuget库 32feet.NET 3.5.0 MaterialDesignColors MaterialDesignThemes Newtonsoft.Json 使用到的技术: XAML ...

  6. 『Flutter』开发环境搭建

    1.前言 大家好,我是 BNTang,今天给大家介绍一下 Flutter 的开发环境搭建.在之前我已经将 Dart 的基本语法给大家介绍了,所以今天就不再介绍 Dart 的基本语法了,直接进入 Flu ...

  7. @Value是个什么东西

    对注解不了解的可以看一下: Java注解,看完就会用 首先我们要明确: @Value 是 Spring 框架的注解. 它有什么作用呢? 作用 @Value 通过注解将常量.配置文件中的值.其他bean ...

  8. C++ 动态库热加载

    C++ 动态库热加载 本文参考自 project-based-learning 中的 Build a Live Code-reloader Library for C++,主要内容都来自于其中,但是对 ...

  9. javacv图片美颜处理,视频美颜处理

    javacv图片美颜处理,视频美颜处理 国产剧明星演戏自带十级滤镜,是众所周知的秘密: 使用opencv也能实现一定的美颜效果: 一.图片美颜 代码 package top.lingkang.test ...

  10. Docker、pre-commit 导致的 git commit 报错:找不到 python 3.8

    到这个问题的原因可能有很多,这里只是记录下针对我遇到这这跟题的原因及解决方法 问题描述 执行 git commit 命令,报错 /usr/bin/env: 'python3.8': No such f ...