【2022-09-29】DRF从入门到入土(四)

drf请求与响应

Request

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

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

常用属性

# 继承APIView后,请求对象:requets---》每一次请求都是一个新的request
# Request类:属性或方法
	data:POST、PUT、PATCH请求方式解析后的数据 
    原生djagno,put提交的数据在request.POST中是取不到的
    query_params
    其他的用起来跟之前一样用(FILES,method,path....--->底层原理  __getattr__

Response

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

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

常用属性

    data=None,   # 字典,列表---》序列化成json格式字符串,返回给前端(放在http响应的body中了)
    status=None,  # http 响应的状态码,默认是200,201   
    drf帮咱们把所有的http响应状态码都做成了常量,可以直接导进来用
    headers=None,      # http的响应头,字典 {name:jason}
    template_name=None, # 了解:在浏览器中看到好看的页面,指定的模板
    content_type=None  # 响应的编码格式(json)

实例

import json
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class Test(APIView):
    def get(self, request):
        d = {'name': 'lisa', 'hobby': 'run'}
        # return HttpResponse(json.dumps(d))
        # return JsonResponse(d)
        # return Response(d, status=status.HTTP_400_BAD_REQUEST, headers={'name': 'jason'})  响应头添加数据,状态码修改

        # 原生Django给响应头里添加数据,使用下面的方法:

        info = HttpResponse(json.dumps(d))
        info['age'] = '18'  
        return info

参数说明

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

响应状态码

# 正常返回信息1xx 
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
# 返回成功2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
# 重定向3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
# 客户端错误4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
# 客户端错误5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

请求编码

# drf默认能够解析三种编码格式:
	urlencoded
    form-data
    json
# 我们创建的项目中没有配置文件,是在drf内置的配置文件中提前配好了,如果需要,可以在我们自己创建的项目中的settings.py文件中配置即可
	-drf也是有两套,一套是项目中得配置(settings.py),一套是默认的配置
    -drf的配置文件settings.py中有 DEFAULT_PARSER_CLASSES(默认的解析类)
           -'rest_framework.parsers.JSONParser', 可以解析json格式
           -'rest_framework.parsers.FormParser', 可以解析urlencoded格式
           -'rest_framework.parsers.MultiPartParser' 可以解析form-data格式
        
    想让我们的接口只能接受json格式
    方式一:全局配置---》项目配置文件---》以后所有的接口都遵循这个配置
    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',
            # 'rest_framework.parsers.FormParser',
            # 'rest_framework.parsers.MultiPartParser',
        ],
    }
    方式二:局部配置
    class TestView(APIView):
        parser_classes = [JSONParser,FormParser,MultiPartParser]

        总结:
        解析类的使用顺序:优先用视图类自己的,然后用项目配置文件,最后用内置的
        实际项目如何配置
        基本上都运行JSONParser,FormParser
        如果上传文件只允许MultiPartParser

响应编码

# 如果用浏览器,好看的样子,如果用postman看到json格式
	-默认请情况下,响应的编码是根据客户端类型决定的
    
# 全局配置:在项目的配置文件
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            # 'rest_framework.renderers.JSONRenderer', # json格式
            'rest_framework.renderers.BrowsableAPIRenderer', #浏览器的格式
        ]
    }

# 局部配置:
class TestView(APIView):
    renderer_classes = [JSONRenderer,]
    
# 实际编码中,响应一般不配,就用默认

drf视图组件

Django REST framwork 提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行

2个视图基类

1  APIView

2  GenericAPIView-->继承了APIView
	-类属性:
    	queryset = User.objects.all()
    	serializer_class = UserSerializer
    -方法:
    	 self.get_object() 	# 根据pk获取单个数据
         self.get_serializer # 获取要使用的序列化类
         self.get_queryset() # 获取所有要序列化数据

自主练习

基于APIView+ModelSerializer写出图书表接口和用户表接口

urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView, BookDetailView, UserView, UserDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view()),
    path('user/', UserView.as_view()),
    path('user/<int:pk>/', UserDetailView.as_view()),
]
models.py
from django.db import models


# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.CharField(max_length=32)
    gender = models.CharField(max_length=32)
    address = models.CharField(max_length=255)


Serializer.py
from rest_framework import serializers
from .models import Book, User


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

views.py
from django.shortcuts import render
from rest_framework.views import APIView
# Create your views here.
from .models import Book, User
from .serializer import BookModelSerializer, UserModelSerializer
from rest_framework.response import Response


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        info = BookModelSerializer(instance=book_list, many=True)
        return Response(info.data)

    def post(self, request):
        info = BookModelSerializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book)
        return Response(info.data)

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'msg': '删除成功'})


class UserView(APIView):
    def get(self, request):
        user_list = User.objects.all()
        info = UserModelSerializer(instance=user_list, many=True)
        return Response(info.data)

    def post(self, request):
        info = UserModelSerializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class UserDetailView(APIView):
    def get(self, request, pk):
        user = User.objects.filter(pk=pk).first()
        info = UserModelSerializer(instance=user)
        return Response(info.data)

    def put(self, request, pk):
        user = User.objects.filter(pk=pk).first()
        info = UserModelSerializer(instance=user, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})

    def delete(self, request, pk):
        User.objects.filter(pk=pk).delete()
        return Response({'msg': '删除成功'})

基于GenericAPIView写出图书表接口和用户表接口

urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView, BookDetailView, UserView, UserDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view()),
    path('user/', UserView.as_view()),
    path('user/<int:pk>/', UserDetailView.as_view()),
]

models.py
from django.db import models


# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.CharField(max_length=32)
    gender = models.CharField(max_length=32)
    address = models.CharField(max_length=255)


Serializer.py
from rest_framework import serializers
from .models import Book, User


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

views.py
from .models import Book, User
from .serializer import BookModelSerializer, UserModelSerializer
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView


class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    def get(self, request):
        book_list = self.get_queryset()
        info = self.get_serializer(instance=book_list, many=True)
        return Response(info.data)

    def post(self, request):
        info = self.get_serializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    def get(self, request, pk):
        book = self.get_object()
        info = self.get_serializer(instance=book)
        return Response(info.data)

    def put(self, request, pk):
        book = self.get_object()
        info = self.get_serializer(instance=book, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})

    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response({'msg': '删除成功'})


class UserView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserModelSerializer

    def get(self, request):
        user_list = self.get_queryset()
        info = self.get_serializer(instance=user_list, many=True)
        return Response(info.data)

    def post(self, request):
        info = self.get_serializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class UserDetailView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserModelSerializer

    def get(self, request, pk):
        user = self.get_object()
        info = self.get_serializer(instance=user)
        return Response(info.data)

    def put(self, request, pk):
        user = self.get_object()
        info = self.get_serializer(instance=user, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})

    def delete(self, request, pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response({'msg': '删除成功'})

继承GenericAPIView+父类写出图书表接口

urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView, BookDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view()),
models.py
from django.db import models


# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.CharField(max_length=32)
    gender = models.CharField(max_length=32)
    address = models.CharField(max_length=255)

Serializer.py
from rest_framework import serializers
from .models import Book, User


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'
	
views.py
from .models import Book, User
from .serializer import BookModelSerializer, UserModelSerializer
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView


class GetBooks(object):
    def get(self, request):
        book_list = Book.objects.all()
        info = BookModelSerializer(instance=book_list, many=True)
        return Response(info.data)


class AddBook(object):
    def post(self, request):
        info = BookModelSerializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class BookView(GenericAPIView, GetBooks, AddBook):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer


class GetBook(object):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book)
        return Response(info.data)


class PutBook(object):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class DeleteBook(object):
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'msg': '删除成功'})


class BookDetailView(GenericAPIView, GetBook, PutBook, DeleteBook):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

基于9个视图子类写出图书表接口

urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView, BookDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookDetailView.as_view()),
]

models.py
from django.db import models


# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.CharField(max_length=32)
    gender = models.CharField(max_length=32)
    address = models.CharField(max_length=255)


Serializer.py
from rest_framework import serializers
from .models import Book, User


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

views.py
from .models import Book
from .serializer import BookModelSerializer
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView


class GetBooks(object):
    def get(self, request):
        book_list = Book.objects.all()
        info = BookModelSerializer(instance=book_list, many=True)
        return Response(info.data)


class AddBook(object):
    def post(self, request):
        info = BookModelSerializer(data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '新增成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class GetBook(object):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book)
        return Response(info.data)


class PutBook(object):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        info = BookModelSerializer(instance=book, data=request.data)
        if info.is_valid():
            info.save()
            return Response({'code': 666, 'msg': '修改成功'})
        else:
            return Response({'code': 777, 'msg': info.errors})


class DeleteBook(object):
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'msg': '删除成功'})


class GettingBooks(GenericAPIView, GetBooks):  # 获取所有
    pass


class AppendBook(GenericAPIView, AddBook):  # 新增
    pass


class AccessToAddBook(GenericAPIView, GetBooks, AddBook):  # 获取+新增
    pass


class GettingBook(GenericAPIView, GetBook):  # 获取单条
    pass


class ChangeBook(GenericAPIView, PutBook):  # 修改
    pass


class RemoveBook(GenericAPIView, DeleteBook):  # 删除
    pass


class AccessToModifyBook(GenericAPIView, GetBook, PutBook):  # 获取单条+修改
    pass


class ModifyDeleteBook(GenericAPIView, PutBook, DeleteBook):  # 修改+删除
    pass


class AccessToDeleteBook(GenericAPIView, DeleteBook, GetBook):  # 删除+获取单条
    pass


class BookView(GettingBooks, AppendBook):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer


class BookDetailView(GettingBook, RemoveBook, ChangeBook):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

图例展示
  • 查询所有图书

  • 查询单个图书

  • 新增单个图书

  • 修改单个图书

  • 删除单个图书

posted @   dy12138  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示