- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
如下是ApiView所有的类属性,我们抽取一部分进行介绍: 可见这些类属性,都是使用drf配置文件的默认配置.
下列策略可以在全局设置 或者 在每一个视图类中设置。 允许依赖注入其他的设置文件, ApiView源码的 settings 类属性使测试更容易 (也就是不使用drf的api_settings) 。
renderer_classes
: 用于设置视图类的响应格式。默认情况会有两种响应格式,一种是响应json字符串,一种是对浏览器的响应。 parser_classes
:用于定义视图类能够解析的请求格式。默认情况下使用3个解析类进行解析,可以解析如下媒体类型: multipart/form-data
, application/x-www-form-urlencoded
, application/json
authentication_classes
:认证类相关配置 throttle_classes
:频率类相关配置 permission_classes
:权限类相关配置 复习:
# APIView跟之前的View区别
-传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
-视图方法可以返回REST framework的Response对象-
-任何APIException异常都会被捕获到,并且处理成合适的响应信息;
-在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
在apiView中使用了drf配置文件的默认配置。以下是配置的查找顺序.
方式三:查找顺序(一般就用内置的即可)
1. 视图类 (局部配置)
2. django settings (全局配置)
3. drf api_settings (内置配置)
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置
在django的settings中应该按照如下格式写:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [ # 配置响应
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
],
'DEFAULT_PARSER_CLASSES': [ # 配置请求
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
# 注意:所有配置都写在一个REST_FRAMEWORK里面!
# 为什么需要进行请求相关配置?
可以定制某些CBV只能只能接收json格式,不能接收其他格式。也就是为了自定义该接口可接受编码格式。
# 默认情况下
前端上传json request.data里面是 ---> python字典
前端上传urlencode\formdata request.data里面是 ---> QueryDict
# 方式一,在继承自APIView及其子类的的视图类中配置(局部配置)
# 总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,]
# 方式二:在配置文件中配置(影响所有,全局配置)
-django有套默认配置,每个项目有个配置
-drf有套默认配置,每个项目也有个配置---》就在django的配置文件中
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
# 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser',
],
}
# 方式三:全局配了1个,某个视图类想要3个,怎么配?
-只需要在视图类,配置3个即可
-因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找
# 视图类方法中的request
-data
-__getattr__
-query_params
# 为什么要在CBV中设置响应相关配置?
因为对于drf的响应,如果使用浏览器和postman访问同一个接口,Response返回的格式是不一样的
-drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据
# 方式一:在视图类中写(局部配置)
-两个响应类---》找---》drf的配置文件中找--》两个类
-from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes=[JSONRenderer,]
# 方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
# 方式三:使用顺序(一般就用内置的即可)
1. renderer_classes
2. django settings
3. drf api_settings
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置
# drf 的Response 源码分析
-from rest_framework.response import Response
-视图类的方法返回时,retrun Response ,走它的__init__, init中可以传什么参数
-Responses最终继承httpresponse.
# Response init可以传的参数
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None)
-data:之前咱们写的ser.data 可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个
-status: http响应的状态码,默认是200,你可以改
-drf在status包下,把所有http响应状态码都写了一遍,常量
-from rest_framework.status import HTTP_200_OK
-Response('dddd',status=status.HTTP_200_OK)
-template_name:了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制
-headers:响应头,http响应的响应头 示例:header={'xxx':'yyy'}
-content_type :响应编码格式,一般不动
# 重点:data,status,headers
# 原生djagno,如何在响应头中加东西?
'''
四件套 render,redirect,HttpResponse,JsonResponse
方法: 产生HttpResponse然后添加属性
'''
# 示例:
obj = HttpResponse('dddd')
obj['xxc'] = 'yyc'
return obj
响应头添加属性涉及知识 ---> 跨域
drf Response提供很多的状态码:
在status内将所有状态码都写了一遍:
from .models import Book
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
# 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books)
return Response(ser.data)
def put(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
### ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
如果需要再新写关于作者的五个接口 ----> 又需要写一个CBV 但是这两个CBV的区别仅仅在于使用的 表模型 和 序列化类 不同,其他都是重复的代码。 这岂不是很麻烦?能不能通过继承的方式,优化代码? 于是就写了一个 GenericAPIview --继承于--> APIView ,以后可以基于这个类来写5个接口.
如果你想使用GenericAPIview,你需要从如下二种选择其一:
在视图类中设置如下属性 (常用) 。
queryset 、 serializer_class 。
重写GenericAPIview类的 get_queryset() / get_serializer_class() 方法 。
如果你重写了一个视图方法,那么重要的是 你应该调用get_queryset() 而不是直接的访问 queryset 属性。 因为 queryset 将只被设置一次,并且为了后续到来的所有请求,这个结果会被缓存.
总而言之,不要直接访问 queryset 、 serializer_class 属性,而是使用GenericAPIview提供的各种方法获取.
# 首先指定模型对象 和 序列化类
class BookView(GenericAPIView):
queryset = Book.objects.all()
# queryset = Book.objects 这样也是可行的
serializer_class = BookSerializer
# 以下代码都是等效的
objs = Book.objects.all()
objs = self.get_queryset()
# 以下代码都是等效的
ser = self.get_serializer(instance=objs, many=True)
BookSerializer(instance=objs, many=True)
get_queryset方法得到视图中的列表对象! 这个列表对象必须是一个可迭代的,也可以是一个queryset对象.
默认使用 self.queryset 来获取(视图中的列表对象):
应该总是使用这个方法来获取,而不是直接调用 self.queryset .
get_queryset源码做了些什么事?
使用 get_serializer() 方法可以返回序列化器的实例,此序列化器,被应用于校验、反序列化前端输入和序列化后端输出.
get_serializer源码做了些什么事?
通过get_serializer_class方法获取了我们在视图类中指定的序列化类 。
添加了一个'context'参数传入我们的序列化类.
相当于 BookSerializer(instance=objs, many=True, context={一些数据...}) 。
get_serializer_class方法基本上什么事情都没有做,直接将序列化器返回,有需求可以重写get_serializer_class。 可以实现:不同的接口使用的序列化类不一样。序列化使用某一个序列化类,反序列化用另一个序列化类.
重写:
这里会根据传入的pk参数查询出对应的模型对象, 正常情况下写查询一个的接口我们需要手动写orm( 比如 Book.objects.filter(pk=pk) ),根据主键将对象查出来。 这里因为使用了GenericAPIview,他会自动帮我们查.
就是通过pk参数和get_object方法将模型对象查询出来的.
返回应用于详细视图的对象实例。默认使用 lookup_field 参数过滤基本的查询集。 该方法可以被重写以提供更复杂的行为,例如基于多个 URL 参数的对象查找.
如果你想使用pk之外的对象查找方式,可以设置lookup_field。如果有更复杂的查找需求,可以重写 get_object() .
以下给出一个示例:
修改查询条件为书籍的名字:
可见在get_object方法中,调用了 get_queryset() 获取了我们放在视图中的queryset,然后使用了 filter_queryset() 对我们从数据库中获取的queryset进行了过滤操作.
关于filter_queryset的解释是: 给他一个queryset,他会使用任何一个你正在使用的后端过滤器,进行过滤.
self.filter_backends :由于我们类中没有配置,所以会指向GenericAPIview类中的filter_backends.
在GenericAPIview类中默认使用的是drf配置文件中指定的默认过滤器.
然后drf配置文件中,默认是不过滤:
所有总而言之,默认就是不过滤,但是我们可以通过在自己的视图类中写 filter_backends 属性,来指定过滤器.
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
def put(self, request, pk):
obj = self.get_object()
ser = self.get_serializer(instance=obj, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
def delete(self, request, pk):
obj = self.get_object()
obj.delete()
return Response({'code': 100, 'msg': '删除成功'})
queryset
- 用于从视图返回对象的查询结果集。通常,你必须设置此属性或者重写 get_queryset()
方法。如果你重写了一个视图的方法,重要的是你应该调用 get_queryset()
方法而不是直接访问该属性,因为 queryset
将被计算一次,这些结果将为后续请求缓存起来。 serializer_class
- 用于验证和反序列化输入以及用于序列化输出的Serializer类。 通常,你必须设置此属性或者重写 get_serializer_class()
方法。 lookup_field
- 用于执行各个model实例的对象查找的model字段。默认为 'pk'
。 请注意,在使用超链接API时,如果需要使用自定义的值,你需要确保在API视图 和 序列化类 都 设置查找字段。 lookup_url_kwarg
- 应用于对象查找的URL关键字参数。它的 URL conf 应该包括一个与这个值相对应的关键字参数。如果取消设置,默认情况下使用与 lookup_field
相同的值。 以下属性用于在与列表视图一起使用时控制分页.
pagination_class - 当分页列出结果时应使用的分页类。默认值与 DEFAULT_PAGINATION_CLASS 设置的值相同,即 'rest_framework.pagination.PageNumberPagination' .
filter_backends - 用于过滤查询集的过滤器后端类的列表。默认值与 DEFAULT_FILTER_BACKENDS 设置的值相同.
虽然使用了GenericAPIview类写五个接口,但是写的代码还是太多了,并没有减少代码呀! CBV类中的方法 get 、 post 、 put 、 delete 代码都是重复的,是不是可以再进行优化?
drf的作者自然想到了这一点,他提供了5个视图扩展类,帮我们写了这一部分代码! 先导入五个视图扩展类:
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
class BookView(GenericAPIView, ListModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
现在就只需要使用 self.list 调用ListModeMixin类中写的代码:
和我们之前写的差不多,先获取queryset然后将其传入序列化类。中间还进行了过滤,分页操作.
class BookDetailView(GenericAPIView, RetrieveModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request, pk): # 注意要传入这个pk
return self.retrieve(request)
这样很方便的就可以实现五个接口,我们只需要知道方法直接的对应关系就行了
ListModelMixin --> list --> 查询所有
RetrieveModelMixin --> retrieve --> 查询一个
CreateModelMixin --> create --> 新增一个
UpdateModelMixin --> update --> 修改一个
DestroyModelMixin --> destroy --> 删除一个
代码:
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request, pk):
return self.retrieve(request)
def put(self, request, pk):
return self.update(request)
def delete(self, request, pk):
return self.destroy(request)
虽然已经简化了代码,但是其实还是有重复的部分比如这些请求方法,之后还会进行封装.
什么叫具体视图类? Concrete View Classes 也就是drf作者已经帮你把CBV需要写的接口代码都写好了,打包成了一个个类,你只需要直接继承这些类,你的视图类就会有相应的接口,是不是很神奇 ~ ~ 。
drf提供如下具体视图类:
注意:没有DestroyUpdateAPIView 。
直接上代码:
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
class BookView(ListCreateAPIView): # 查询所有 新增一个
queryset = Book.objects
serializer_class = BookSerializer
class BookDetailView(RetrieveUpdateDestroyAPIView): # 查询一个 修改一个 删除一个
queryset = Book.objects
serializer_class = BookSerializer
之前我们使用两个CBV写五个接口的原因是: 查询一个和查询所有都是使用get请求,为了解耦合,避免在类中的get方法中写太多代码,所以将其拆成两个CBV.
而使用ModelViewSet可以实现,一个视图类写5个接口.
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet):
queryset = Book.objects
serializer_class = BookSerializer
最后此篇关于【Djangodrf】视图类APIView之五层封装ApiView的类属性drf配置文件的文章就讲到这里了,如果你想了解更多关于【Djangodrf】视图类APIView之五层封装ApiView的类属性drf配置文件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景 我有一个定义了多个自定义操作的 ModelViewSet。我在 urls.py 中使用默认路由器注册 URL。现在,我的 View 使用默认创建的路由,如 ^images/$ , ^images
DRF 中的 request.data 和 DRF 中的 serializers.data 有什么区别。 当我在 DRF 中编写基于函数的 View 时,我会像使用它们一样 - eli
我用Django REST框架准备了API。我正在使用docker运行我的API,一切在我的机器上都运行得很好。因此,我只需运行docker-compose up,就可以在浏览器中使用Swagger测
我用Django REST框架准备了API。我正在使用docker运行我的API,一切在我的机器上都运行得很好。因此,我只需运行docker-compose up,就可以在浏览器中使用Swagger测
1. 源码分析 注意:以下代码片段为方便理解已进行简化,只保留了与序列化功能相关的代码 序列化的源码中涉及到了元类的概念,我在这里简单说明一下:元类(metaclass)是一个高级概念,用于定义类
1. 解析器源码分析 注意:以下源码为了方便理解已进行简化,只保留了解析器相关的代码 # 视图函数: class MyView(APIView): def post(self, reque
快速上手JWT签发token和认证,有这一篇就够了,DRF自带的和自定义的都帮你总结好了,拿去用~ DRF JWT认证(二) 上篇中对JWT有了基本的认知,这篇来略谈JWT的使用 签发:一般我们登录成
什么接口文档都不用手写了?自动挡? DRF 自动生成接口文档 我们知道前后端分离,前端一般按后端写好的接口去开发,那么就需要我们明细后端接口数据等,需要写接口文档,前端按照接口文档去开发 接口文档如何
为什么要使用JWT认证?构成和原理又是什么?怎么还有Base64的事?我都写了👆 DRF JWT认证(一) JWT认证 Json web token (JWT), 是为了在网络应用环境间传递声明而执
DRF 中如何使用过滤,排序,分页,以及报错了如何处理?10分钟get了~ DRF 过滤排序分页异常处理 过滤 涉及到查询数据的接口才需要过滤功能 DRF过滤使用种类: 内置过滤类 第三方 自定义 内
前后端分离开发怎么给接口做认证权限频率三大认证?点进来5分钟get! DRF-认证权限频率 前后端混合开发,可以通过HttpResponse对象来设置cookie进而校验登录,现在前后端分离开发,用不
你问我使用DRF视图组件快速写接口?九九归一剑诀早就准备好了,没有副作用! DRF 视图组件 DRF框架提供了很多通用的视图基类与扩展类,上篇使用的APIView是比较偏Base的,视图的使用更加简化
1、路由Routers 在 Rest Framework 中提供了两个 router , 可以帮助我们快速的实现路由的自动生成。 必须是继承 ModelViewSet 的视图类才能自动生成路由
1. 前言 大家好,我是安果! 接下来,将通过几篇文章将对 DRF 模型序列化进行展开说明,详情谈谈模型序列化的作用、步骤及进阶用法 2. 模型序列化的作用?  
我第一次尝试进入 Django 原子事务。我想知道是否有可能像这样使用它: class TaskViewSet(MultiSerializerViewSet): @transaction.at
我有一个 drf 序列化程序,其中有一个我想重命名的字段: class UserBulkUploadSerializer(serializers.Serializer): ... is
我使用了 drf 并且还使用了 serializer 来检查用户输入。 这是我的serializer.py class BoardSerializer(serializers.Serializer):
我正在尝试序列化一个 CreateUserSerializer(ModelSerializer)我的代码如下。我的问题是它只会创建一个 User 而不是 UserProfile。 模型.py clas
我如何发布这个 JSON { "campaign": 27, "campaignName": "Prueba promo", "promotionType": 999, "items"
我正在构建一个 todo 应用程序,可以在 todo 上发布评论。 为此,我制作了一个可写的双嵌套序列化程序。它有效,但我编写的更新方法难以理解,因此我试图使其更具可读性。是否有更好的(或标准的)方法
我是一名优秀的程序员,十分优秀!