rest_framework_django 学习笔记二(视图路由)

news2024/11/24 23:19:56

rest_framework_django 学习笔记二(视图路由)

rest_framwork_django学习笔记一(序列化器)

一、rest framework 中Request 与 Response

1、Request

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,二是REST Famework 提供的扩展了 Http Request 类的Request 类的对象。

REST framework 提供了 Parser 解析器,在接受到请求后悔自藕丁工具Content-Type 指明的请求数据类型(如JSON、表单等)将请求数据就行parse 解析,解析为类字典对象保存到Request对象中。

Request对象的数据时自动工具前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

常用属性

1).data

request.data 返回解析之后的请求数据 类似于django中标准的 request.POST 和request.FILES属性,但提供如下特性:

  • 包含了解析之后的文件和非文件数据;
  • 包含了对POST,PUT,PATCH请求方式解析后的数据;
  • 利用REST ftamework 的parsers 解析器,不仅支持表单类型数据,也支持JSON数据;
2).query_params

request.query_params 与 django标准的 request.GET 相同,只是更换了更准确的名称而已。

2、Response

rest_framework.response.Response

REST framework 提供了一个响应类 Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

REST framework 提供了 Renderer 渲染器,用来工具请求头中的 Accept (接收数据类型声明)来自自动转换响应数据到对应格式。如果前端请求中为进行 Accept 声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。

# settings.py
# ================================================= #
# ***************** REST_FRAMEWORK **************** #
# ================================================= #
REST_FRAMEWORK = {
	"DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S",  # 日期时间格式配置
	"DATE_FORMAT": "%Y-%m-%d",
	'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.renderers.JONSRenderer',#json 渲染器
        'rest_framework.renderers,BrowsableAPIRenderer',# 浏览API渲染器
    ],
}

构造方式

Response(data,status=None,template_name=None,headers=None,content_type=None)

data 数据不要是 render 处理之后的数据,只是传递 python 的内建类型数据即可,REST framework 会使用 renderer 渲染器处理 data .

data不能是复杂结构的数据,如 Django的模型对象,对于这样的数据我们可以使用 Serializer 序列化器序列化处理后(转为了python字典类型)再传递给 data 参数。

参数说明:

  • data:为响应准备的序列化处理后的数据;
  • status:状态吗,默认200;
  • template_name:末班名称,如果使用HTMLRenderer 时需要指明;
  • headers:用于存放响应头信息的字典;
  • content_type:响应数据的Content_type,通常此参数无需传递,REST framework 会工具前端所需类型数据来设置该参数。

常用属性

1).data

传给 response 对象的序列化后,但尚未 render 处理的数据

2).status_code

状态码的数字

3).content

结果 render 处理后的响应数据

状态码

为了方便设置状态码 REST framework 在 rest_framework.status 模块中提供了常用状态码常量。

rest_framework.status
1)信息告知 - 1xx
HTTP_100_CONTINUE = 100
HTTP_101_SWITCHING_PROTOCOLS = 101
HTTP_102_PROCESSING = 102
HTTP_103_EARLY_HINTS = 103
2) 成功 - 2xx
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_202_ACCEPTED = 202
HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
HTTP_204_NO_CONTENT = 204
HTTP_205_RESET_CONTENT = 205
HTTP_206_PARTIAL_CONTENT = 206
HTTP_207_MULTI_STATUS = 207
HTTP_208_ALREADY_REPORTED = 208
HTTP_226_IM_USED = 226
3)重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES = 300
HTTP_301_MOVED_PERMANENTLY = 301
HTTP_302_FOUND = 302
HTTP_303_SEE_OTHER = 303
HTTP_304_NOT_MODIFIED = 304
HTTP_305_USE_PROXY = 305
HTTP_306_RESERVED = 306
HTTP_307_TEMPORARY_REDIRECT = 307
HTTP_308_PERMANENT_REDIRECT = 308
4)客户端错误 - 4xx
HTTP_400_BAD_REQUEST = 400
HTTP_401_UNAUTHORIZED = 401
HTTP_402_PAYMENT_REQUIRED = 402
HTTP_403_FORBIDDEN = 403
HTTP_404_NOT_FOUND = 404
HTTP_405_METHOD_NOT_ALLOWED = 405
HTTP_406_NOT_ACCEPTABLE = 406
HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
HTTP_408_REQUEST_TIMEOUT = 408
HTTP_409_CONFLICT = 409
HTTP_410_GONE = 410
HTTP_411_LENGTH_REQUIRED = 411
HTTP_412_PRECONDITION_FAILED = 412
HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
HTTP_414_REQUEST_URI_TOO_LONG = 414
HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
HTTP_417_EXPECTATION_FAILED = 417
HTTP_418_IM_A_TEAPOT = 418
HTTP_421_MISDIRECTED_REQUEST = 421
HTTP_422_UNPROCESSABLE_ENTITY = 422
HTTP_423_LOCKED = 423
HTTP_424_FAILED_DEPENDENCY = 424
HTTP_425_TOO_EARLY = 425
HTTP_426_UPGRADE_REQUIRED = 426
HTTP_428_PRECONDITION_REQUIRED = 428
HTTP_429_TOO_MANY_REQUESTS = 429
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
5)服务端错误 - 5xx
HTTP_500_INTERNAL_SERVER_ERROR = 500
HTTP_501_NOT_IMPLEMENTED = 501
HTTP_502_BAD_GATEWAY = 502
HTTP_503_SERVICE_UNAVAILABLE = 503
HTTP_504_GATEWAY_TIMEOUT = 504
HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
HTTP_507_INSUFFICIENT_STORAGE = 507
HTTP_508_LOOP_DETECTED = 508
HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
HTTP_510_NOT_EXTENDED = 510
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511

自定义返回

# -*- coding: utf-8 -*-
from rest_framework.response import Response

class SuccessResponse(Response):
    """
    标准响应成功的返回, SuccessResponse(data)或者SuccessResponse(data=data)
    (1)默认code返回2000, 不支持指定其他返回码
    """

    def __init__(self, data=None, msg='success', status=None, template_name=None, headers=None, exception=False,
                 content_type=None,page=1,limit=1,total=1):
        std_data = {
            "code": 2000,
            "data": {
                "page": page,
                "limit": limit,
                "total": total,
                "data": data
            },
            "msg": msg
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


class DetailResponse(Response):
    """
    不包含分页信息的接口返回,主要用于单条数据查询
    (1)默认code返回2000, 不支持指定其他返回码
    """

    def __init__(self, data=None, 
                 msg='success', 
                 status=None, 
                 template_name=None, 
                 headers=None, 
                 exception=False,
                 content_type=None,):
        std_data = {
            "code": 2000,
            "data": data,
            "msg": msg
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


class ErrorResponse(Response):
    """
    标准响应错误的返回,ErrorResponse(msg='xxx')
    (1)默认错误码返回400, 也可以指定其他返回码:ErrorResponse(code=xxx)
    """

    def __init__(self, data=None, msg='error', code=400, status=None, template_name=None, headers=None,
                 exception=False, content_type=None):
        std_data = {
            "code": code,
            "data": data,
            "msg": msg
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


二、视图

1、两个基类

1.1 APIView

rest_framework.views.APIView

APIView 是 REST framework 提供的所有视图的基类,继承自django的 view 父类

APIView 与 view 的不同之处在于:

  • 传入到视图方法中的是REST framework 的 request 对象,而不是 django 的 HttpRequest 对象;
  • 视图方法可以返回 REST framework 的 Response 对象,视图会响应数据设置(render)符合前端要求的格式;
  • 任何 APIException 异常都会被捕获到,并且处理成合适的响应学习;
  • 在进行 dispatch() 分发前,会对请求进行身份认证、权限检查、流量控制

支持定义的属性:

  • authentication_classes 列表或原则,身份认证类;
  • permissoin_classes 列表或元祖,权限检查类;
  • throttle_classes 列表或元祖,流量控制类;

在 APIView 中仍以常规的类视图定义方法来实现 get()\post() 或者其他请求方式的方法。

''' 序列化器 '''
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = '__all__'
''' urls.py '''
urlpatterns = [
		path('publish/',PublishListAPIView.as_view()),# 列表视图
		path('publish/<int:id>/',PublishDetaAPIView.as_view()),# 详情视图
]
1)查询列表
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *


class PublishListAPIView(APIView):
	''' 列表视图 '''
	def get(self,request):
		''' 查询所有 '''
		publish_list = Publish.objects.filter()
		serializer = PublishSerializer(instance=publish_list, many=True)
		return Response(serializer.data)

在这里插入图片描述

2)增
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *
class PublishListAPIView(APIView):
	''' 列表视图 '''
	def get(self,request):
		''' 查询所有 '''
		publish_list = Publish.objects.filter()
		serializer = PublishSerializer(instance=publish_list, many=True)
		response = Response(data=serializer.data)
		return response
		# return Response(serializer.data)
	def post(self,request):
		''' 新增 '''
		# 1、获取前端传入的数据
		data = request.data
		# 2、创建序列化器进行反序列化
		serializer = PublishSerializer(data=data)
		# 3、调用序列化器 is_valid 方法进行校验
		serializer.is_valid(raise_exception=True)
		# 4、调用序列化器的save() 方法进行执行 create 方法
		serializer.save()
		# 5、响应
		return Response(serializer.data)

在这里插入图片描述

3)删
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *
from rest_framework import status
class PublishDetaAPIView(APIView):
	''' 详情列表 '''
	def delete(self,request,id):
		try:
			publish = Publish.objects.filter(pk=id).first()
		except Publish.DoesNotExist:
			return Response(status=status.HTTP_404_NOT_FOUND)
		publish.delete()
		return Response(status=status.HTTP_200_OK)

在这里插入图片描述

4)改
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *
from rest_framework import status

class PublishDetaAPIView(APIView):
	''' 详情列表 '''
	def put(self,request,id):
		''' 修改 '''
		# 1、查询修改内容
		publish_obj = Publish.objects.filter(pk=id).first()
		if not publish_obj:
			return Response(status=status.HTTP_404_NOT_FOUND)
		# 2、获取前端出入的请求体数据
		data = request.data
		# 3、创建序列化器进行反序列化
		serializer = PublishSerializer(instance=publish_obj,data=data)
		# 4、校验
		serializer.is_valid(raise_exception=True)
		serializer.save()
		# 5、保存
		return Response(serializer.data)

在这里插入图片描述

增删查改代码全

''' urls.py'''
urlpatterns = [
	path('publish/',PublishListAPIView.as_view()),# 列表视图  增加、查询数据列表
	path('publish/<int:id>/',PublishDetaAPIView.as_view()),# 详情视图  删除、单一查询、修改
]
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
    ''' 序列化器 '''
    class Meta:
        model = Publish
        fields = '__all__'
from django.db import models
''' models.py '''
class Publish(models.Model):
	name = models.CharField(max_length=32)
	city = models.CharField(max_length=64)
	email = models.EmailField()
	class Meta:
		verbose_name = '出版社表'
# coding=utf-8
'''
@date:2023/11/20 13:37
@mail:xiaochun235@qq.com
@Content:
APIView 序列化器
'''
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *
from rest_framework import status


class PublishListAPIView(APIView):
	''' 列表视图 '''
	def get(self,request):
		''' 查询所有 '''
		publish_list = Publish.objects.filter()
		serializer = PublishSerializer(instance=publish_list, many=True)
		response = Response(data=serializer.data)
		return response
		# return Response(serializer.data)
	def post(self,request):
		''' 新增 '''
		# 1、获取前端传入的数据
		data = request.data
		# 2、创建序列化器进行反序列化
		serializer = PublishSerializer(data=data)
		# 3、调用序列化器 is_valid 方法进行校验
		serializer.is_valid(raise_exception=True)
		# 4、调用序列化器的save() 方法进行执行 create 方法
		serializer.save()
		# 5、响应
		return Response(serializer.data)

class PublishDetaAPIView(APIView):
	''' 详情列表 '''
	def get(self,request,id):
		''' 查询 pk  '''
		# 查询pk
		publish_obj = Publish.objects.filter(pk = id).first();
		if not publish_obj:
			return Response(status=status.HTTP_404_NOT_FOUND)
		# 将查询内容序列化
		serializer = PublishSerializer(instance = publish_obj)
		# 响应
		response = Response(data=serializer.data)
		return response
	def put(self,request,id):
		''' 修改 '''
		# 1、查询修改内容
		publish_obj = Publish.objects.filter(pk=id).first()
		if not publish_obj:
			return Response(status=status.HTTP_404_NOT_FOUND)
		# 2、获取前端出入的请求体数据
		data = request.data
		# 3、创建序列化器进行反序列化
		serializer = PublishSerializer(instance=publish_obj,data=data)
		# 4、校验
		serializer.is_valid(raise_exception=True)
		serializer.save()
		# 5、保存
		return Response(serializer.data)
	def delete(self,request,id):
		''' 删除 '''
		try:
			publish = Publish.objects.filter(pk=id).first()
		except Publish.DoesNotExist:
			return Response(status=status.HTTP_404_NOT_FOUND)
		publish.delete()
		return Response(status=status.HTTP_200_OK)

1.2 GenericAPIView

在这里插入图片描述

rest_framework.generics.GenericAPIView

继承自 APIVIew,主要增加了操作序列化器和数据查询的方法,作用是为了Mixin扩展类的执行提供方法支持,通常在使用时,可搭配一个或多个 Mixin扩展类

提供的相关序列化器使用的属性与方法

属性:
  • serializer_class 指明视图使用的序列化器
方法:
  • get_serializer_class(self)

返回序列化器类,默认范湖 serializer_class,可以 重写。例如:

def get_serializer_class(self):
	if self.request.user.is_staff:
		return FullAccounSerializer
	return BasicAccountSerializer
  • get_serializer(self,args,*Kwargs)

返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象也可以直接调用此方法。

注意,该方法在提供序列化器对象的时候,会向序列化器对象的 context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

  • request 当前视图的请求对象
  • view 当前请求的类视图对象
  • format 当前请求期望返回的数据格式
提供的关于数据库查询的属性与方法
属性:
  • queryser 指明使用的数据查询集
方法:
  • get_queryset(self)

返回视图使用的查询集,主要用来提供给Mixin 扩展使用,是列表视图与相求视图获取数据的基础,默认返回 queryset 属性,可以重写,例如:

def  get_queryset(self):
	user = self.request.user
	return  user.accounts.all()
  • get_object(self)

返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。

在视图中可以调用该方法获取详情学习的模型类对象。

若详情访问的模型类对象不存在,会返回404.

该方法默认使用 APIView 提供的check_object_permissions 方法检查当前对象是否有权限被访问。

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import *
from .serializers import *

class PublishListGenericAPIView(GenericAPIView):
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,reqest):
		publish = self.get_queryset() # 获取所有数据
		serializer = self.get_serializer(publish,many=True)# 构造序列化器对象
		return Response(data=serializer.data)
class PublishDetaGenericAPIView(GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,request,pk):
		''' 查询 单一'''
		publish = self.get_object()# 查询单一
		serializer = self.get_serializer(publish)
		return Response(data=serializer.data)

urls.py

from .generic_apiview_views import *
from django.urls import path
urlpatterns = [
	# GenericAPIView
	path('publish/',PublishListGenericAPIView.as_view()),# 列表视图
	# GenericAPIView
	path('publish/<int:pk>/',PublishDetaGenericAPIView.as_view()),# 详情视图
]

在这里插入图片描述

其他扩展
  • pagination_class 指明分页控制类
  • filter_backends 指明过滤控制后端
  • ordering_fields 指明过滤中的排序后端
  • authentication_classes 指明认证后端
  • permission_classes 指明权限后端
1)查询、修改、单个查询
from .generic_apiview_views import *
from django.urls import path
urlpatterns = [
	# GenericAPIView
	path('publish/',PublishListGenericAPIView.as_view()),# 列表视图
	# GenericAPIView
	path('publish/<int:pk>/',PublishDetaGenericAPIView.as_view()),# 详情视图
]
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import *
from .serializers import *

class PublishListGenericAPIView(GenericAPIView):
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,reqest):
		'''
		'''
		publish = self.get_queryset() # 获取所有数据
		serializer = self.get_serializer(publish,many=True)# 构造序列化器对象
		return Response(data=serializer.data)


class PublishDetaGenericAPIView(GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,request,pk):
		''' 查询 单一'''
		publish = self.get_object()# 查询单一
		serializer = self.get_serializer(publish)
		return Response(data=serializer.data)
	def put(self,request,pk):
		publish = self.get_object()
		serializer = self.get_serializer(publish,request.data)
		serializer.is_valid(raise_exception = True)
		serializer.save()
		return Response(serializer.data)
2) 整合 Mixin 实现简单增删查改操作
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.mixins import ListModelMixin,CreateModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin
from .serializers import *

class PublishListGenericAPIView(ListModelMixin,CreateModelMixin,GenericAPIView):
   # 指定序列化器的 类
   serializer_class = PublishSerializer
   # 指定查询集 ’数据来源‘
   queryset = Publish.objects.all()
   def get(self,request):
      ''' 查询 '''
      return self.list(request=request)
   def post(self,request):
      ''' 新增 '''
      return self.create(request)
class PublishDetaGenericAPIView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,request,pk):
		''' 查询 单一'''
		return self.retrieve(request,pk)
	def put(self,request,pk):
		''' 修改 '''
		return self.update(request,pk)
	def delete(self,request,pk):
		''' 删除 '''
		return self.destroy(request,pk)

在这里插入图片描述

3) 简化后的 GenericApiView增删查改
from .generic_apiview_views import *
from django.urls import path
urlpatterns = [
	# GenericAPIView
	path('publish/',PublishListGenericAPIView.as_view()),# 列表视图
	# GenericAPIView
	path('publish/<int:pk>/',PublishDetaGenericAPIView.as_view()),# 详情视图
]
rest_framework.generics.ListAPIView # 列表查询
rest_framework.generics.CreateAPIView # 新增
rest_framework.generics.UpdateAPIView  # 修改
rest_framework.generics.DestroyAPIView  #删除 
rest_framework.generics.RetrieveAPIView # 查询一条数据
rest_framework.generics.ListCreateAPIView  # 列表查询 + 新增
rest_framework.generics.RetrieveUpdateDestroyAPIView # 单个查询,修改,删除
from rest_framework.generics import GenericAPIView,\
	ListAPIView,\
	CreateAPIView,\
	UpdateAPIView,\
	DestroyAPIView,\
	RetrieveAPIView,\
	ListCreateAPIView,\
	RetrieveUpdateDestroyAPIView
from .serializers import *

class PublishListGenericAPIView(ListCreateAPIView,GenericAPIView):
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()

class PublishDetaGenericAPIView(RetrieveUpdateDestroyAPIView,GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()

在这里插入图片描述

在这里插入图片描述

2、视图集ViewSet

2.1 ViewSet

使用视图集 ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  • list() 提供一组数据
  • retrieve() 提供单个数据
  • create() 创建数据
  • update() 保存数据
  • destory() 删除数据

ViewSet 视图集类不再实现 get()、post() 等方法,而是实现动作 action 如list()、create() 等。

视图集只在使用 as_view() 方法的时候,才会到 action 动作与具体请求方式对应上,如:

from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from .serializers import PublishSerializer
from .models import *

class PublishViewset(ViewSet):
	def list(self,request):
		objects_filter = Publish.objects.filter()
		serializer = PublishSerializer(instance=objects_filter,many=True)
		return Response(data=serializer.data)
	def add(self,request):
        ''' 方法未实现 '''
		pass
	def delete(self,request,pk):
         ''' 方法未实现 '''
		pass
	def get_by(self,request,pk):
		objects_filter = Publish.objects.filter(pk=pk).first()
		serializer = PublishSerializer(instance=objects_filter)
		return Response(data=serializer.data)
	def update(self,request,pk):
         ''' 方法未实现 '''
		pass

在设置路由时,我们可以如下操作:

from .view_set_views import *
from django.urls import path
urlpatterns = [
	# GenericAPIView
	path('publish/',PublishViewset.as_view({'get':'list','post':'add'})),# 列表视图
	# GenericAPIView
	path('publish/<int:pk>/',PublishViewset.as_view({'get':'get_by','delete':'delete','put':'update'})),# 详情视图
]

在这里插入图片描述

继承自 APIView 与ViewSetMixin ,作用也与APIView 基本类似,提供了身份认证、权限校验、流量管理等。

ViewSet 主要通过继承ViewSetMixin 来实现在调用 as_view() 时传入字典(如{‘get’:‘list’})的映射处理工作。

在ViewSet中,没有提供如何动作 action 方法,需要我们自己实现 action 方法

2.2 GenericViewset

使用ViewSet 通常并不方便,因为list、retrieve、create、update、destory 等方法都需要自己编写、而这些方法与前面讲的 Mixin 扩展类提供的方法同名,所以我们可以通过继承 Mixin 扩展类来服用这些方法而无需自己编写,但是Mixin扩展类依赖于 GenericAPIView ,所以还需要继承 GenericAPIView.

GenericViewSet 就帮助我们完成了这样的继承工作,继承自 GenericAPIView 与 ViewSetMixin,在实现了调用as_view() 时传入字典(如{‘get’:‘list’})的映射处理工作同时,还提供了 GenericAPIView 提供的基础方法,可以直接搭配Minxin 扩展类使用。

举例:

urls.py

from .view_set_views import *
from django.urls import path
urlpatterns = [
	# GenericViewSet 整合 mixins
	path('publish/',PublishViewset.as_view({'get':'list','post':'create'})),# 列表视图
	# GenericViewSet 整合 mixins
	path('publish/<int:pk>/',PublishViewset.as_view({'get':'retrieve','delete':'destroy','put':'update'})),# 详情视图
]
''' 原始 GenericViewSet  配合 mixin  '''
from rest_framework.viewsets import ViewSet,GenericViewSet,ReadOnlyModelViewSet
from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin
from .serializers import PublishSerializer
from .models import *
class PublishViewset(GenericViewSet,ListModelMixin,RetrieveModelMixin,CreateModelMixin,DestroyModelMixin,UpdateModelMixin):
	''' 视图集 '''
	queryset = Publish.objects.all()
	serializer_class = PublishSerializer

在这里插入图片描述

2.3ReadOnlyModelViewSet

在这里插入图片描述

rest_framework.viewsets.ReadOnlyModelViewSet
from rest_framework.viewsets import GenericViewSet,ReadOnlyModelViewSet,ModelViewSet
from .serializers import PublishSerializer
from .models import *
class PublishViewset(ReadOnlyModelViewSet,ModelViewSet):
	''' 视图集 '''
	queryset = Publish.objects.all()
	serializer_class = PublishSerializer

在这里插入图片描述

2.4ModelViewSet

rest_framework.viewsets.ModelViewSet

在这里插入图片描述

3、视图集中定义附加 action 动作

3.1 增加自定义方法

from .view_set_views import *
from django.urls import path
from .book_views import BookModelViewSet
urlpatterns = [
	path('book/', BookModelViewSet.as_view({'get': 'list', 'post': 'create'})),  # 列表视图
	path('book/<int:pk>/', BookModelViewSet.as_view({'get': 'retrieve', 'delete': 'destroy', 'put': 'update'})),
	# 详情视图
	path('book/get_book', BookModelViewSet.as_view({'get': 'get_book'})),  # 通过获取大于 多少钱的书
	path('book/<int:pk>/update_book_price', BookModelViewSet.as_view({'put': 'update_book_price'})),  # 修改书的价格
]
from django.db.models import Q
from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import Book
from rest_framework.response import Response
class BookModelViewSet(ModelViewSet):
	queryset = Book.objects.all()
	serializer_class = BookSerializer
	def get_book(self,request):
		''' 查询 price 大于data['price']的书 '''
		data = request.data
		book_qy = Q(price__gt=data['price'])
		book_list = Book.objects.filter(book_qy)  # 工具id获取最后一本书
		serializer = self.get_serializer(book_list,many=True)
		return Response(serializer.data)
	def update_book_price(self,request,pk):
		''' 修改某一本书的价格 '''
		book_object = self.get_object()
		book_object.price = request.data['price']
		book_object.save()
		serializer = self.get_serializer(book_object)
		return Response(serializer.data)

在这里插入图片描述

4、总结

4.1APIView

在APIView中的request直接叫 request;

django中的响应对象叫HttpResponse,而APIView中的叫Response;

APIView中新增了异常捕获;

在APIView中可以用序列化器;

''' urls.py '''
urlpatterns = [
		path('publish/',PublishListAPIView.as_view()),# 列表视图
		path('publish/<int:id>/',PublishDetaAPIView.as_view()),# 详情视图
]
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from .serializers import *
from rest_framework import status
class PublishListAPIView(APIView):
	''' 列表视图 '''
	def get(self,request):
		''' 查询所有 '''
		publish_list = Publish.objects.filter()
		serializer = PublishSerializer(instance=publish_list, many=True)
		response = Response(data=serializer.data)
		return response
		# return Response(serializer.data)
	def post(self,request):
		''' 新增 '''
		# 1、获取前端传入的数据
		data = request.data
		# 2、创建序列化器进行反序列化
		serializer = PublishSerializer(data=data)
		# 3、调用序列化器 is_valid 方法进行校验
		serializer.is_valid(raise_exception=True)
		# 4、调用序列化器的save() 方法进行执行 create 方法
		serializer.save()
		# 5、响应
		return Response(serializer.data)

class PublishDetaAPIView(APIView):
	''' 详情列表 '''
	def get(self,request,id):
		''' 查询 pk  '''
		# 查询pk
		publish_obj = Publish.objects.filter(pk = id).first();
		if not publish_obj:
			return Response(status=status.HTTP_404_NOT_FOUND)
		# 将查询内容序列化
		serializer = PublishSerializer(instance = publish_obj)
		# 响应
		response = Response(data=serializer.data)
		return response
	def put(self,request,id):
		''' 修改 '''
		# 1、查询修改内容
		publish_obj = Publish.objects.filter(pk=id).first()
		if not publish_obj:
			return Response(status=status.HTTP_404_NOT_FOUND)
		# 2、获取前端出入的请求体数据
		data = request.data
		# 3、创建序列化器进行反序列化
		serializer = PublishSerializer(instance=publish_obj,data=data)
		# 4、校验
		serializer.is_valid(raise_exception=True)
		serializer.save()
		# 5、保存
		return Response(serializer.data)
	def delete(self,request,id):
		''' 删除 '''
		try:
			publish = Publish.objects.filter(pk=id).first()
		except Publish.DoesNotExist:
			return Response(status=status.HTTP_404_NOT_FOUND)
		publish.delete()
		return Response(status=status.HTTP_200_OK)

4.2GenericAPIView

GenericAPIView 继承的就是 APIView;

GenericAPIView 增加了分页和过滤功能;

''' urls.py '''
urlpatterns = [
		path('publish/',PublishListAPIView.as_view()),# 列表视图
		path('publish/<int:id>/',PublishDetaAPIView.as_view()),# 详情视图
]
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import *
from .serializers import *

class PublishListGenericAPIView(GenericAPIView):
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,reqest):
		publish = self.get_queryset() # 获取所有数据
		serializer = self.get_serializer(publish,many=True)# 构造序列化器对象
		return Response(data=serializer.data)
class PublishDetaGenericAPIView(GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,request,pk):
		''' 查询 单一'''
		publish = self.get_object()# 查询单一
		serializer = self.get_serializer(publish)
		return Response(data=serializer.data)
1) GenericAPIView + Minxin
''' urls.py '''
urlpatterns = [
		path('publish/',PublishListAPIView.as_view()),# 列表视图
		path('publish/<int:id>/',PublishDetaAPIView.as_view()),# 详情视图
]
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.mixins import ListModelMixin,CreateModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin
from .serializers import *

class PublishListGenericAPIView(ListModelMixin,CreateModelMixin,GenericAPIView):
   # 指定序列化器的 类
   serializer_class = PublishSerializer
   # 指定查询集 ’数据来源‘
   queryset = Publish.objects.all()
   def get(self,request):
      ''' 查询 '''
      return self.list(request=request)
   def post(self,request):
      ''' 新增 '''
      return self.create(request)
class PublishDetaGenericAPIView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,GenericAPIView):
	''' 详情视图 '''
	# 指定序列化器的 类
	serializer_class = PublishSerializer
	# 指定查询集 ’数据来源‘
	queryset = Publish.objects.all()
	def get(self,request,pk):
		''' 查询 单一'''
		return self.retrieve(request,pk)
	def put(self,request,pk):
		''' 修改 '''
		return self.update(request,pk)
	def delete(self,request,pk):
		''' 删除 '''
		return self.destroy(request,pk)

4.3 ViewSet

from .views import *
from django.urls import path
urlpatterns = [
    # 可以使用 路由器
	# ViewSet
	path('publish/',PublishViewset.as_view({'get':'list','post':'add'})),# 列表视图
	# ViewSet
	path('publish/<int:pk>/',PublishViewset.as_view({'get':'get_by','delete':'delete','put':'update'})),# 详情视图
]

from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from .serializers import PublishSerializer
from .models import *

class PublishViewset(ViewSet):
	def list(self,request):
		objects_filter = Publish.objects.filter()
		serializer = PublishSerializer(instance=objects_filter,many=True)
		return Response(data=serializer.data)
	def add(self,request):
		# 注意序列化器中 的第一个参数是 instance 第二个是 data,当没写时,默认从第一个开始
		serializer = self.get_serializer(data=request.data)
		serializer.is_valid(raise_exception=True)
		serializer.save()
		return Response(data=serializer.data)
	def delete(self,request,pk):
		''' 删除 '''
		publish = self.get_object()  # 查询单一
		publish.delete()
		return Response()
	def get_by(self,request,pk):
		objects_filter = Publish.objects.filter(pk=pk).first()
		serializer = PublishSerializer(instance=objects_filter)
		return Response(data=serializer.data)
	def update(self,request,pk):
		get_object = self.get_object()
		serializer = self.get_serializer(get_object, request.data)
		serializer.is_valid(raise_exception=True)
		serializer.save()
		return Response(data=serializer.data)

4.4GenericViewSet

from .views import *
from django.urls import path
urlpatterns = [
    # 可以使用 路由器
	# ViewSet
path('publish/',PublishViewset.as_view({'get':'list','post':'create'})),# 列表视图
	# ViewSet
path('publish/<int:pk>/',PublishViewset.as_view({'get':'retrieve','delete':'destroy','put':'update'})),# 详情视图
]
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from .serializers import PublishSerializer
from .models import *
class PublishViewset(GenericViewSet):
	queryset = Publish.objects.filter()
	serializer_class = PublishSerializer
	def list(self,request):
		data_lis = self.get_queryset()
		serializer = self.get_serializer(data_lis, many=True)
		return Response(data=serializer.data)
	def retrieve(self,request,pk):
		''' 查询 单一'''
		publish = self.get_object()  # 查询单一
		serializer = self.get_serializer(publish)
		return Response(data=serializer.data)
	def destroy(self,request,pk):
		''' 删除 '''
		publish = self.get_object()  # 查询单一
		publish.delete()
		return Response()
	def update(self,request,pk):
		''' 修改 '''
		get_object = self.get_object()
		serializer = self.get_serializer(get_object, request.data)
		serializer.is_valid(raise_exception=True)
		serializer.save()
		return Response(data=serializer.data)
	def create(self,request):
		''' 新增 '''
		# 注意序列化器中 的第一个参数是 instance 第二个是 data,当没写时,默认从第一个开始
		serializer = self.get_serializer(data=request.data)
		serializer.is_valid(raise_exception=True)
		serializer.save()
		return Response(data=serializer.data)

1) GenericViewSet + Minxin
from .view_set_views import *
from django.urls import path
urlpatterns = [
    # 可以使用 路由器
	# GenericAPIView
	path('publish/',PublishViewset.as_view({'get':'list','post':'create'})),# 列表视图
	# GenericAPIView
	path('publish/<int:pk>/',PublishViewset.as_view({'get':'retrieve','delete':'destroy','put':'update'})),# 详情视图
]
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,\
	RetrieveModelMixin,\
	CreateModelMixin,\
	UpdateModelMixin,\
	DestroyModelMixin
from rest_framework.response import Response
from .serializers import PublishSerializer
from .models import *
class PublishViewset(GenericViewSet,ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin):
    # 由于 mixins 中 已经将重用的方法写了,不用在写 也可以自行重写。
	queryset = Publish.objects.filter()
	serializer_class = PublishSerializer

4.5 ModelViewSet

from rest_framework.viewsets import ModelViewSet
from .serializers import PublishSerializer
from .models import *
class PublishViewset(ModelViewSet):
    ''' ModelViewSet 已经继承了mixins中常用的内容 '''
	queryset = Publish.objects.filter()
	serializer_class = PublishSerializer

在这里插入图片描述

三、路由器

路由器只能配合视图一起使用

视图集:ViewSet、GenericViewSet 、ModelViewSet

rest_framework.routers.DefaultRouter

路由器只会生成默认的五个路由

在这里插入图片描述

其余的还需要自己手动加入

路由器使用方法:

from rest_framework.routers import DefaultRouter
urlpatterns = [] # 其他手动加入的路由内容
router = DefaultRouter()# 创建路由器
router.register('book',BookModelViewSet,basename='book')# 注册路由
urlpatterns += router.urls# 把生成好的路由拼接到urlpatterns中去

自定义增加的行为

@action(methods=[‘get’],detail=False)

action 中的参数

methods 表示的是 请求方式

detail 表示的是 路由生成方式;当detail=True 时会生成的url 则是 book/+ **PK/方法名/ ** 当 detail=False 时会生成 book/+ **方法名/ **

rest_framework.decorators.action
from django.db.models import Q
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from .serializers import BookSerializer
from .models import Book
from rest_framework.response import Response
class BookModelViewSet(ModelViewSet):
	queryset = Book.objects.all()
	serializer_class = BookSerializer
	# datail 为 False 表示路径名格式应该为:  books/get_book/
	@action(methods=['get'],detail=False)
	def get_book(self,request):
		''' 查询 price 大于data['price']的书 '''
		data = request.data
		book_qy = Q(price__gt=data['price'])
		book_list = Book.objects.filter(book_qy)  # 工具id获取最后一本书
		serializer = self.get_serializer(book_list,many=True)
		return Response(serializer.data)

	# datail 为 True 表示路径名格式应该为:  books/pk/update_book_price/
	@action(methods=['put'], detail=True)
	def update_book_price(self,request,pk):
		''' 修改某一本书的价格 '''
		book_object = self.get_object()
		book_object.price = request.data['price']
		book_object.save()
		serializer = self.get_serializer(book_object)
		return Response(serializer.data)
''' urls.py '''
from .book_views import BookModelViewSet
from rest_framework.routers import DefaultRouter
urlpatterns = []
router = DefaultRouter()# 创建路由器
router.register('book',BookModelViewSet,basename='book')# 注册路由
urlpatterns += router.urls# 把生成好的路由拼接到urlpatterns中去

在这里插入图片描述

DefaultRouter

rest_framework.routers.DefaultRouter

SimpleRouter

rest_framework.routers.SimpleRouter

注意:

SinmpleRouter 和 DefaultRouter 只有一个区别,DefaultRouter 会多生成一个根路由

其他笔记

序列化器

视图路由

异常、登录认证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1274392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git解决冲突

记录一次 git 解决冲突的过程。 情况是前一段时间我基于本地的 master 分支上新建了一个分支比如叫做 weight_linear: git checkout -b weight_linear 然后我已经在这个分支上进行了修改并上传到 github 上了&#xff0c;比如&#xff1a; git add . git commit -m "u…

uc_09_创建新进程 exec() system()

1 什么是创建新进程(夺舍) 在前面文章中&#xff0c;我们学习了fork()函数用来创建子进程。 子进程是父进程的副本&#xff0c;复制父进程除代码段以外的其他数据&#xff0c;代码段数据和父进程共享。 子进程的PID与父进程不同&#xff1a; 而创建新进程则不同。 与fork()不同…

传统算法: Pygame 实现深度优先搜索(DFS)

使用 Pygame 模块实现了深度优先搜索(DFS)的动画演示。首先,它通过邻接矩阵表示了一个图的结构,其中每个节点表示一个字符,每个字符的邻居表示与之相邻的节点。然后,通过深度优先搜索算法递归地访问所有节点,过程中通过动画效果可视化每一步的变化。每次访问一个节点,该…

数据爬虫(JSON格式)数据地图可视化(pyecharts)【步骤清晰,一看就懂】

一、前言 数据存储在网页上&#xff0c;需要爬取数据下来&#xff0c;数据存储格式是JSON&#xff0c;数据可视化在工作中也变得日益重要&#xff0c;接下来将数据爬虫与数据可视化结合起来&#xff0c;做个案例 注&#xff1a;当时数据是22年1月29日爬取数据 二、使用步骤 …

嵌入式数据传输及存储的C语言实现

各种类型的数据传输和存储就涉及到大小端的问题&#xff0c;首先要简单说下芯片的大小端问题&#xff0c;这里主要讨论Cortex-M内核。 M内核支持大端或者小端&#xff0c;实际应用中大部分内核都是小端。以STM32为例&#xff0c;全部都是小端&#xff0c;而且是芯片设计之初就固…

TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】

文章目录 一.转发路由器 Transit Router 测评1.1 准备阶段1.2 本文测评收获1.3 什么是云企业网实例、转发路由器实例和云数据传输服务 二.使用云企业网实现跨地域跨VPC的网络互通2.2 **测试连通性**2.3 网络拓扑如下&#xff1a; 心得&#xff1a;总结&#xff1a; 声明&#x…

Vue+SpringBoot解决session跨域问题

做了一个前后端分离&#xff0c;因为前后端的 session id不一致&#xff0c;导致前端请求时&#xff0c;后端的session读取不到对应的值&#xff0c;造成登录问题。 解决方法&#xff1a; SpringBoot项目: 添加一个跨域配置 代码如下: 或者controller使用CrossOrigin Conf…

解决noauth authentication required异常

今天在使用redis数据库的时候&#xff0c;突然给报了个这个错误&#xff0c;上网一查才知道是因为 Redis 服务器需要密码进行身份验证&#xff0c;因此&#xff0c;我们需要通过auth password 进行身份验证。不过我这个密码还是试了很多次才想起来的&#xff0c;哦好像是听网课…

WSL2 docker GUI 界面

在 WSL2 docker 中运行GUI界面。 具体流程和远程显示Ubuntu界面类似&#xff0c;链接, 更简单一点&#xff0c; 少了 ssh 的部分。 安装好wsl2 和 docker wsl2 运行GUI程序&#xff0c;windows 会默认弹出窗口。 可以安装 gedit 测试一下 windows 下载并运行 Xlaunch. 运行 d…

【驱动】SPI驱动分析(二)-SPI驱动框架

SPI驱动框架 SPI驱动属于总线-设备-驱动模型的&#xff0c;与I2C总线设备驱动模型相比&#xff0c;大体框架是一样&#xff0c;他们都是实际的总线。总体框架如下图所示&#xff1a; 从上到下&#xff0c;分为三层&#xff0c;用户空间&#xff0c;内核空间&#xff0c;和硬件…

微信小程序真机调试的时候出现白屏解决办法

我使用uniapp开发微信小程序开发&#xff0c;使用真机调试的时候&#xff0c;出现白屏&#xff0c;页面里面啥都没有&#xff0c;也没有报错&#xff0c;这就让人很纳闷了&#xff1a; 解决办法&#xff1a; 打开真机调试&#xff0c;下面有&#xff1a;切换真机调试1.0&#…

RocketMQ-RocketMQ快速实战及集群原理

一、MQ简介 ​ MQ&#xff1a;MessageQueue&#xff0c;消息队列。是在互联网中使用非常广泛的一系列服务中间件。 这个词可以分两个部分来看&#xff0c;一是Message&#xff1a;消息。消息是在不同进程之间传递的数据。这些进程可以部署在同一台机器上&#xff0c;也可以分布…

虚拟机系列:Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置

Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置 Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置 在更新Oracle VM Virtua…

泛型和数据结构(树)

一&#xff1a;泛型的基本知识 泛型是用来约束操作的数据类型&#xff0c;并进行检查 基本格式&#xff1a;<数据类型> 注意&#xff1a;泛型只能支持引用数据类型&#xff0c;如果是基本数据类型&#xff0c;需要写他的包装类 先来看一下没有泛型约束的集合 我们发现此时…

【ArcGIS Pro二次开发】(78):批量合并GDB数据库

有些GDB数据库会按分幅或行政区划进行分开储存&#xff0c;尤其是一些地形测绘或国情地理数据。 如下图所示&#xff1a; 数据是完整的&#xff0c;但使用的时候要一个一个拖进地图中&#xff0c;进行分析的时候也需要将其合并后使用。 因此就做了这个合库工具。 一、要实现的…

万界星空科技仓库管理wms系统

企业在管理库存时&#xff0c;尤其是生产制造企业&#xff0c;使用传统方式比如纸笔、Excel 管理库存&#xff0c;由于工具和信息化存在局限&#xff0c;导致在管理库存时出现如下问题&#xff1a; 1、通过纸笔记录出入库申请&#xff0c;人为手动计算易出错&#xff0c;数据易…

[iOS学习笔记]浅谈RunLoop底层

RunLoop是什么&#xff1f; RunLoop是iOS开发中比较重要的知识点&#xff0c;它贯穿程序运行的整个过程。它是线程基础架构的一部分&#xff0c;是一种保障线程循环处理事件而不会退出的机制。同时也负责管理线程需要处理的事件&#xff0c;让线程有事儿时忙碌&#xff0c;没事…

键盘敲入一个字母,操作系统发生了什么?

一、设备控制器 我们的电脑设备可以接非常多的输入输出设备&#xff0c;比如鼠标键盘网卡硬盘打印机等&#xff0c;每个设备的用法和功能都不相同&#xff0c;那操作系统是如何把这些输入输出设备统一管理的呢&#xff1f; 为了屏蔽设备之间的差异&#xff0c;每个设备都有一…

rest_framework_django学习笔记一(序列化器)

rest_framework_django学习笔记一(序列化器) 一、引入Django Rest Framework 1、安装 pip install djangorestframework2、引入 INSTALLED_APPS [...rest_framework, ]3、原始RESTful接口写法 models.py from django.db import models 测试数据 仅供参考 INSERT INTO de…

我与开源的历程

我在2000年开始接触开源&#xff0c;当时在松下航空电子美国总部工作。我负责将 IFE 系统从 Win31 迁移到 Linux。作为一个完全不懂 Linux 的小白&#xff0c;我不得不找到一台笔记本电脑安装并自学 Redhat Linux 6.1。2003年回到新加坡后&#xff0c;我发现没有一个凝聚 Linux…