欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Django DRF routers路由使用

程序员文章站 2022-07-12 11:11:54
...

代码下载:利用django自带的routers实现对url路由的分发(代码实战)

我们常用的定义url的路由有以下两种方式:

第一种:

urlpatterns = [
    url('^student/$',StudentViewSetAction.as_view({'get':'list','post':'create'}))
]

第二种:

# coding:utf-8
from rest_framework import routers
from api.views import *

router = routers.DefaultRouter()
router.register(r'student', StudentViewSetAction, base_name='student')

urlpatterns = []
urlpatterns += router.urls

下面主要讲解第二种方式,第一种比较常见且简单。

1、配置app下面的settings、urls和models。

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,

}
# coding:utf-8
from rest_framework import routers
from api.views import *

router = routers.DefaultRouter()
router.register(r'student', StudentViewSetAction, base_name='student')

urlpatterns = []
urlpatterns += router.urls
# coding:utf-8
from django.db import models


class Teacher(models.Model):
    """老师表"""
    name = models.CharField(verbose_name="老师姓名", max_length=16)
    motto = models.CharField(verbose_name="格言", max_length=32)


class Student(models.Model):
    """学生表"""
    tea = models.ForeignKey(Teacher, on_delete=models.DO_NOTHING, verbose_name="老师")
    name = models.CharField(verbose_name="学生姓名", max_length=16)
    add_time = models.DateField(verbose_name='添加日期', auto_now_add=True)
    age = models.IntegerField(verbose_name='年龄')

 

2、配置视图。

# coding:utf-8
from django.db import transaction
from django_filters import rest_framework
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from api import models
from api.utils.filter import getUserListFilter
from api.utils.ser import getUserListSerializer
from rest_framework import filters
from rest_framework.decorators import action


class StudentViewSetAction(ModelViewSet):
    '''学生视图'''
    queryset = models.Student.objects.all()
    serializer_class = getUserListSerializer  # 数据序列化
    filter_backends = (
        rest_framework.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,)  # 需要用django查询的固定写法
    filter_class = getUserListFilter  # 定义过滤查询
    ordering_fields = ('tea', 'id')  # 排序的字段

    def list(self, request, *args, **kwargs):
        '''获取学生列表分页'''
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def create(self, request, *args, **kwargs):
        '''新增学生信息'''
        return Response({'method': '新增学生信息'})

    def update(self, request, pk, *args, **kwargs):
        '''修改学生信息'''
        return Response({'method': '修改学生信息'})

    '''
       detail: 声明该action的路径是否与单一资源对应,及是否是xxx/<pk>/action方法名/
       True 表示路径格式是xxx/<pk>/action方法名/
       False 表示路径格式是xxx/action方法名/
    '''

    @action(methods=['get'], detail=False)
    def read(self, request, *args, **kwargs):
        """
            自定义获取
        """
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @action(methods=['post'], detail=False)
    def add(self, request, *args, **kwargs):
        """
            自定义新增
        """

        return Response({'method': '这个方法也是新增'})

    @action(methods=['put'], detail=True)
    def edit(self, request, pk, **kwargs):
        """
            自定义修改
        """

        return Response({'method': '这个方法也是修改'})

3、配置filter过滤类和ser序列化类。

filter:

# coding:utf-8
import django_filters
from django_filters import rest_framework as filters

from api import models


class ProductSourceNameListFilter(django_filters.CharFilter):
    def filter(self, qs, value):
        value = list(filter(None, value.split(",")))
        return super(ProductSourceNameListFilter, self).filter(qs=qs, value=value)


class getUserListFilter(django_filters.rest_framework.FilterSet):
    # method one
    # tea = ProductSourceNameListFilter(field_name='tea', lookup_expr='in')

    # method two
    tea = filters.CharFilter(method='filter_tea', lookup_expr='in')
    name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
    min_age = django_filters.NumberFilter(field_name='age', lookup_expr='gt')
    max_age = django_filters.NumberFilter(field_name='age', lookup_expr='lt')

    class Meta:
        model = models.Student
        fields = ['name', 'tea', 'min_age', 'max_age', 'add_time']  # 允许精准查询的字段
        search_fields = ['name', ]  # 允许模糊查询的字段,上面需要定义

    def filter_tea(self, queryset, name, value):
        value_list = list(filter(None, value.split(",")))
        order_ids = models.Student.objects.filter(tea__in=value_list)
        return queryset.filter(id__in=order_ids)

ser:

# coding:utf-8
from rest_framework import serializers

from api import models


class getUserListSerializer(serializers.ModelSerializer):
    '''student模型序列化'''
    # teaname = serializers.CharField(label="老师姓名", source="tea.name")
    # motto = serializers.CharField(label="老师姓名", source="tea.motto")
    # days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = models.Student
        fields = '__all__'
        # depth = 1  # 向下取的深度

    # 方法写法:get_ + 字段
    def get_days_since_joined(self, obj):
        # obj指这个model的对象
        return '%s-24' % obj.name

4、请求路由列表。

http://127.0.0.1:8000/api/student/read/?name=zh&tea=&add_time=2019-07-10&min_age=1&max_age=55   GET

http://127.0.0.1:8000/api/student/?name=&tea=&add_time=2019-07-10&min_age=1&max_age=55  GET

http://127.0.0.1:8000/api/student/ POST

http://127.0.0.1:8000/api/student/add/   POST

http://127.0.0.1:8000/api/student/1/   PUT

http://127.0.0.1:8000/api/student/a/edit/  PUT

两种方法比较:

router.register(.....)这种方法相比于url,可以少些很多路由,直接在方法中用@action定义就行。