Day62ジャンゴ-DRFのビュー依存

 

  3.ステータスコード

ステータスコードを設定容易にするために、RESTフレームワークはrest_framework.statusモジュールに共通のステータスコード定数を提供します。

 --- 1XXを通知する3.1情報

HTTP_100_CONTINUE 
HTTP_101_SWITCHING_PROTOCOLS

3.2成功--- 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

3.3リダイレクト--- 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

3.4クライアントエラー--- 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

3.5 服务器错误---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

 

 

具体代码参考:https://www.cnblogs.com/Michael--chen/p/11235456.html

用到的序列化器类:

from students.models import Student
from rest_framework import serializers


class StudentModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = Student
        fields = ["id", "name", "age", "sex"]
        extra_kwargs = {
            "name": {"max_length": 10, "min_length": 4},
            "age": {"max_value": 150, "min_value": 0},
        }

    def validate_name(self, data):
        if data == "root":
            raise serializers.ValidationError("用户名不能为root!")
        return data

    def validate(self, attrs):
        name = attrs.get('name')
        age = attrs.get('age')

        if name == "alex" and age == 22:
            raise serializers.ValidationError("alex在22时的故事。。。")

        return attrs

 

对应的urls的文件:

urlpatterns = [
    # View与APIView的区别
    path("student1/", views.Student1View.as_view()),
    path("student2/", views.Student2APIView.as_view()),
]

 

views.py文件:

from django.views import View
from django.http import JsonResponse


class Student1View(View):
    def get(self, request):
        print(request)  # 这是django提供的HttpRequest类
        print(request.GET)
        """打印效果:
        <WSGIRequest: GET '/req/student1/'>
        """
        data_dict = {'name': "alex", "age": 18}

        return JsonResponse(data_dict)


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


class Student2APIView(APIView):
    def get(self, request):
        print(request)  # rest_framework扩展后的request
        print(request.query_params)
        print(request.data)
        """打印效果
        <rest_framework.request.Request object at 0x00000000054D8898>
        """
        data_dict = {'name': "alex", "age": 18}

        return Response(data_dict, status=status.HTTP_204_NO_CONTENT, headers={"name": "xiaobai"})

 

小结:
1.使用Django的View时候,
导包:
from django.views import View
from django.http import JsonResponse
最初的老办法一步一步开
2.使用drf的View时候:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
3.返回的方式是drf是根据你的需要就行返回,比较灵活。

 

 

urls.py中的文件:
  path("student4/", views.Student5GenericAPIView.as_view()),
    re_path(r"^student4/(?P<pk>\d+)/$", views.Student6GenericAPIView.as_view()),
]

 下图中的5改为4.

小结:1.最大改变是

 # 当前视图类中操作的公共数据,先从数据库查询出来
    queryset = Student.objects.all()
    # 设置类视图中所有方法共有调用的序列化器类
    serializer_class = StudentModelSerializer

 

2.调用值的方式的改变。从GenericAPIView开始发生变化

#1.self.get_queryset() 获取数据库中的所有对象
# 类似于之前的在数据库中查询:
student_list = Student.objects.all()这个也是和APIView的区别。
# 2.# 调用序列化器
 serializer = self.get_serializer(instance=student_list, many=True)

 

在4的基础上就行再次的封装!

# 不带参数的,GenericApIView的

# 带参数的

# 和不带参数的GenericApIView加上同样的2条之后还有第三条:

#1.  # 获取pk值对应的对象
        instance = self.get_object()
# 2.生成serializer对象时候,和上面差不多
serializer = self.get_serializer(instance=instance, data=request.data)
# 3. pk值是没有管的,直接获取self.get_object()

 

class Student6GenericAPIView(GenericAPIView):
    # 当前视图类中操作的公共数据,先从数据库查询出来
    queryset = Student.objects.all()
    # 设置类视图中所有方法共有调用的序列化器类
    serializer_class = StudentModelSerializer

    def get(self, request, pk):
        """参数pk名,必须要叫pk,否则会报错。"""
        # 获取模型对象
        instance = self.get_object()
        serializer = self.get_serializer(instance=instance)

        return Response(serializer.data)

    def put(self, request, pk):
        instance = self.get_object()

        serializer = self.get_serializer(instance=instance, data=request.data)

        serializer.is_valid(raise_exception=True)

        serializer.save()

        return Response(serializer.data)

    def delete(self, request, pk):
        # 获取模型对象
        instance = self.get_object()
        # 删除模型对象
        instance.delete()

        return Response(status=status.HTTP_204_NO_CONTENT)

 

 在上面5的基础上就行进一步的封装.

url中的代码:

 path("student5/", views.Student7GenericAPIView.as_view()), 不带参数的是访问模式可以是最开始的Get获取所有数据功能,POST增加单条数据。
 re_path(r"^student5/(?P<pk>\d+)/$", views.Student8GenericAPIView.as_view()),# 带参数的,可以是对应到最开始的PUT/Delete/update对应到这个地方封装的
ListModelMixin      实现查询所有数据功能 get
CreateModelMixin    实现添加数据的功能 post
RetrieveModelMixin  实现查询一条数据功能get
UpdateModelMixin    更新一条数据的功能 update
DestroyModelMixin   删除一条数据的功能 destroy

 

from rest_framework.mixins import ListModelMixin, CreateModelMixin


class Student7GenericAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin


class Student8GenericAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    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)

 

小结:中间代码的环节不用写了,在内部封装好了!

比如上面的get方法中的

 def get(self, request, pk):
        """参数pk名,必须要叫pk,否则会报错。"""
        # 获取模型对象
        instance = self.get_object()
        serializer = self.get_serializer(instance=instance)

        return Response(serializer.data)

 

只需要写出函数名和返回值即可。

 urls.py中的代码:

 # 使用内置的扩展子类,生成API接口
    path("student6/", views.Student9GenericAPIView.as_view()),
    re_path(r"^student6/(?P<pk>\d+)/$", views.Student10GenericAPIView.as_view()),

 

在6的基础上就行封装!

"""
DRF里面,内置了一些同时继承了GenericAPIView和Mixins扩展类的视图子类,
我们可以直接继承这些子类就可以生成对应的API接口
"""

"""
ListAPIView      获取所有数据
CreateAPIView    添加数据
"""
from rest_framework.generics import ListAPIView, CreateAPIView


class Student9GenericAPIView(ListAPIView, CreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer


"""
RetrieveAPIView                 获取一条数据
UpdateAPIView                   更新一条数据
DestorAPIView                   删除一条数据
RetrieveUpdateDestoryAPIView    上面三个的缩写
"""
from rest_framework.generics import RetrieveUpdateDestroyAPIView


class Student10GenericAPIView(RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
复制代码

 

 

视图集
上面5个接口使用了8行代码生成,但是我们可以发现有一半的代码重复了
所以,我们要把这些重复的代码进行整合,但是依靠原来的类视图,其实有2方面产生冲突的
1. 查询所有数据、添加数据是不需要声明pk的,而其他的接口需要    [路由冲突了]
2. 查询所有数据和查询一条数据,都是属于get请求                 [请求方法冲突了]
为了解决上面的2个问题,所以DRF提供了视图集来解决这个问题

 urls.py中的代码:

 path("student7/", views.Student11GenericAPIView.as_view({"get": "list", "post": "create"})),
    re_path(r"^student7/(?P<pk>\d+)/$", views.Student11GenericAPIView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

 掌握最后一个就可以了!,直接在视图的位置就行指定,就可以达到对应的访问。无敌!

from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin


# 这两个是等价的
# class Student11GenericAPIView(GenericViewSet, ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin):
class Student11GenericAPIView(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

 

おすすめ

転載: www.cnblogs.com/longerandergou/p/11240651.html