Django Rest Framework(一)

•基于Django

先创建一个django项目,在项目中创建一些表,用来测试rest framework的各种组件

class UserInfo(models.Model):
    """用户信息表"""
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)


class UserToken(models.Model):
    """用户token表"""
    user = models.OneToOneField(to="UserInfo", on_delete=models.CASCADE)
    token = models.CharField(max_length=64)


class Courses(models.Model):
    """
    课程表
    """
    name = models.CharField(verbose_name="课程名称", max_length=32)
    course_img = models.CharField(verbose_name="课程图片", max_length=64)
    level_choices = (
        (1, "初级"),
        (2, "中级"),
        (3, "高级"),
    )
    level = models.IntegerField(verbose_name="难度", choices=level_choices, default=1)

    def __str__(self):
        return self.name


class CourseDetail(models.Model):
     """课程详细表"""
     course = models.OneToOneField(to="Courses", on_delete=models.CASCADE)
     slogan = models.CharField(verbose_name="口号", max_length=255)
     why = models.CharField(verbose_name="为什么要学", max_length=255)
     recommend_courses = models.ManyToManyField(verbose_name="推荐课程", to="Courses",
                                                related_name="rc")  # related_name设置反向查询的字段,有多个关联时指定某个字段进行反向查询

    def __str__(self):
         return "课程详细:" + self.course.title



class Chapter(models.Model):
    """
    课程章节表
    """
    num = models.IntegerField(verbose_name="章节")
    name = models.CharField(verbose_name="章节名称", max_length=32)
    course = models.ForeignKey(verbose_name="所属课程", to="Courses", related_name='coursechapters', on_delete=models.CASCADE)

    def __str__(self):
        return self.name
models.py
from django.contrib import admin
from django.urls import path, include, re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^api/(?P<version>\w+)/', include("api.urls")),
]
urls.py
from django.urls import re_path
from api.views import courses, account, micro

urlpatterns = [
    re_path(r'^courses/$', courses.CoursesView.as_view({"get": "list"})),
    re_path(r'^courses/(?P<pk>\d+)/', courses.CoursesView.as_view({"get": "retrieve"})),

    re_path(r'^micro/$', micro.MicroView.as_view({"get": "list"})),

    re_path(r'^login/$', account.LoginView.as_view()),
]
api/urls.py

 

•基本流程

请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发不同的方法,返回不同的内容
url.py
from django.conf.urls import url, include
from api.views import TestView
 
urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
 
 
class TestView(APIView):
    def dispatch(self, request, *args, **kwargs):
        """
        请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法
         
        注意:dispatch方法有好多好多的功能
        """
        return super().dispatch(request, *args, **kwargs)
 
    def get(self, request, *args, **kwargs):
        return Response('GET请求,响应内容')
 
    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')
 
    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

 

•路由系统

a.半自动路由

from django.contrib import admin
from django.urls import include, re_path
from api.views import courses


urlpatterns = [
    re_path(r'^courses/$', courses.CoursesView.as_view({'get': 'list', 'post': 'create'})),
    re_path(r'^courses/(?P<pk>\d+)/', courses.CoursesView.as_view(
        {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]
urls.py
# -*- coding:utf-8 -*-
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from api import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer
views.py

b.全自动路由

from django.conf.urls import url, include
from rest_framework import routers
from api.views import users


router = routers.DefaultRouter()
router.register(r'users', users.UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]
urls.py
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from api import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer
views.py

 

•视图系统

a.ModelViewSet自定义URL

from django.urls import include, re_path
from api.views import courses


urlpatterns = [
    re_path(r'^courses/$', courses.CoursesView.as_view({'get': 'list', 'post': 'create'})),
    re_path(r'^courses/(?P<pk>\d+)/', courses.CoursesView.as_view(
        {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]
urls.py
# -*- coding:utf-8 -*-
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from api import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer
views.py

b.ModelViewSet(rest framework路由)

from django.conf.urls import url, include
from rest_framework import routers
from api.views import users


router = routers.DefaultRouter()
router.register(r'users', users.UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]
urls.py
from rest_framework import viewsets
from rest_framework import serializers
from api import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(viewsets.ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer
views.py

 

•版本控制

基于url的正则方式传入版本参数进行版本控制:/v1/girls/

settings.py

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # 参数,URL中获取值的key
}

urls.py

from django.urls import path, include, re_path

urlpatterns
= [ re_path(r'^api/(?P<version>\w+)/', include("api.urls")), ]

单个视图设置版本

views.py

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning


class TestView(APIView):
    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)

        return Response('GET请求,响应内容')

全局设置

settings.py

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS": 'rest_framework.versioning.URLPathVersioning',
    "ALLOWED_VERSIONS": ['v1', 'v2'],   # 允许的版本
    "VERSION_PARAM": 'version',         # 参数
    "DEFAULT_VERSION": 'v1',            # 默认版本
}

•解析器(parser)

根据请求头content-type选择对应的解析器处理请求体内容

a.只处理请求头content-type为application/json的请求体

views.py

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser


class TestView(APIView):
    parser_classes = [JSONParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)return Response('POST请求,响应内容')

b. 只处理请求头content-type为application/x-www-form-urlencoded 的请求体

views.py

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser


class TestView(APIView):
    parser_classes = [FormParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的FormParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)

        return Response('POST请求,响应内容')

c. 只处理请求头content-type为multipart/form-data的请求体

views.py

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser

class TestView(APIView):
    parser_classes = [MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的MultiPartParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)

        return Response('POST请求,响应内容')

d.只处理上传文件

views.py

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser


class TestView(APIView):
    parser_classes = [FileUploadParser, ]

    def post(self, request, filename, *args, **kwargs):
        print(filename)
        print(request.content_type)

        # 获取请求的值,并使用对应的FileUploadParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

e.同时使用多个Parser

views

# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser


class TestView(APIView):
    parser_classes = [JSONParser, FormParser, MultiPartParser, ]

    def post(self, request, filename, *args, **kwargs):
        print(request.content_type)

        # 当同时使用多个parser时,rest framework会根据请求头content-type自动进行比对,并使用对应parser
        print(request.data)

        return Response('POST请求,响应内容')

全局设置:

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]

}

 

•渲染器

访问url时将数据渲染出不同的格式进行显示

a.浏览器格式API+JSON

单个视图设置

views.py

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

from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import BrowsableAPIRenderer

from api import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()


class TestView(APIView):
    renderer_classes = [CustomBrowsableAPIRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().first()
        ser = TestSerializer(instance=user_list, many=False)
        return Response(ser.data)

全局设置

settings.py

REST_FRAMEWORK = {
    "DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer",
                                 "rest_framework.renderers.BrowsableAPIRenderer"],
}

 

posted @ 2019-01-25 21:36  ZivLi  阅读(155)  评论(0编辑  收藏  举报