• django rest framework暴露api


    一、创建序列化模型文件serializers.py

    class Course(models.Model):
        """
        课程
        """
        title = models.CharField(verbose_name="课程名称", max_length=128)
        course_img = models.CharField(verbose_name="课程图片", max_length=128)
        level_choices = (
            (1,"初级"),
            (2,"中级"),
            (3,"高级"),
        )
        level = models.IntegerField(verbose_name="难易程度", choices=level_choices, default=1)
    
        def __str__(self):
            return self.title
    
    class CourseDetail(models.Model):
        """
        课程详细
        """
        course = models.OneToOneField(to="Course", on_delete=models.CASCADE)
        slogon = models.CharField(verbose_name="口号", max_length=255)
        why = models.CharField(verbose_name="为什么要学?", max_length=255)
        recommend_course = models.ManyToManyField(verbose_name="推荐课程", to="Course", related_name="rc")
    
        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="Course", on_delete=models.CASCADE)
    
        def __str__(self):
            return self.name
    models.py
    from api.models import *
    from rest_framework import serializers
    
    
    class CourseSerializer(serializers.ModelSerializer):
        level = serializers.CharField(source="get_level_display")
    
        class Meta:
            model = Course
            fields = '__all__'
    
    
    class CourseDetailSerializer(serializers.ModelSerializer):
        # one2one/fk/choice字段可以直接取出数据,m2m字段会返回一个queryset列表
        title = serializers.CharField(source="course.title")    # source引用本model字段的外键值作为新增"fields"的值
        img = serializers.CharField(source="course.course_img")
        level = serializers.CharField(source="course.get_level_display") # 获取choice的对应值,需要使用get_field_display()方法
                                                                        # restframework源码内部会判断"()"是否该添加
    
        # m2m字段取数据,需要自定义方法,这里使用SerializerMethodField,方法名称get_field(),这里定义get_recommends()方法。
        # class Meta中的fields需要明确字段值,字段值必须与通过这里使用SerializerMethodField()生成的实例对象名相等。
        recommends = serializers.SerializerMethodField()
        chapter = serializers.SerializerMethodField()
    
        class Meta:
            model = CourseDetail
            fields = ["course","title","img","level","slogon","why","recommends","chapter"]
            # depth = 2 # 定义返回数据的深度,可以将外键数据库中对应的值全部返回。
    
        # m2m字段取数据
        def get_recommends(self, obj):
            queryset = obj.recommend_course.all()
            return [{"id":row.id, "title":row.title} for row in queryset]
    
        # 字段为外键,并且需要反向查找取数据
        def get_chapter(self, obj):
            queryset = obj.course.chapter_set.all()
            return [{"id":row.id, "name":row.name} for row in queryset]

    二、使用序列化文件,并对queryset进行序列化

    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from api import models
    from api.serializers import CourseSerializer,CourseDetailSerializer
    
    class CourseView(APIView):
        # renderer_classes = [JSONRenderer,]
        def get(self, request, *args, **kwargs):
            ret = {"code":1000, "data":None}
            try:
                pk = kwargs.get("pk")
                if pk:
                    obj = models.Course.objects.filter(pk=pk).first()
                    ser = CourseSerializer(instance=obj, many=False)
                else:
                    queryset = models.Course.objects.all()
                    ser = CourseSerializer(instance=queryset, many=True)
                ret["data"] = ser.data
            except Exception as e:
                ret["code"] = 1001
                ret["error"] = "获取课程失败"
            return Response(ret)

    三、在路由文件中添加路由

    from api.views import course
    
    urlpatterns = [
        path("course/", course.CourseView.as_view()),
        re_path("course/(?P<pk>d+)", course.CourseView.as_view()),
    ]

    优化

    urlpatterns = [
        path("course/", course.CourseView.as_view({"get":"list"})),
        re_path("course/(?P<pk>d+)", course.CourseView.as_view({"get":"retrieve"})),
    ]
    from rest_framework.viewsets import ViewSetMixin
    
    class CourseView(ViewSetMixin, APIView):
        def list(self, request, *args, **kwargs):
            ret = {"code": 1000, "data": None}
            try:
                queryset = models.Course.objects.all()
                ser = CourseSerializer(instance=queryset, many=True)
                ret["data"] = ser.data
            except Exception as e:
                ret["code"] = 1001
                ret["error"] = "获取课程失败"
            return Response(ret)
    
        def retrieve(self, request, *args, **kwargs):
            ret = {"code": 1000, "data": None}
            try:
                pk = kwargs.get("pk")
                queryset = models.CourseDetail.objects.filter(course_id=pk)
                ser = CourseDetailSerializer(instance=queryset, many=True)
                ret["data"] = ser.data
            except Exception as e:
                ret["code"] = 1001
                ret["error"] = "获取课程详细信息失败"
            return Response(ret)

    rest framework中,如果想要在as_view()中添加变量来确定请求方式,需要继承ViewSetMixin

    四、说明

    rest framework中,如果想要对特殊的字段进行序列化设置,比如:ForeignKey、OneToOneField、ManyToManyField,需要单独配置。另外,如果需要进行字段反向查询,也需要单独设置。choice数据取出中文,需要使用get_field_display()方法

    one2one/fk/choice字段设置
    # one2one/fk/choice字段可以直接取出数据,m2m字段会返回一个queryset列表
        title = serializers.CharField(source="course.title")    # source引用本model字段的外键值作为新增"fields"的值
        img = serializers.CharField(source="course.course_img")
        level = serializers.CharField(source="course.get_level_display") # 获取choice的对应值,需要使用get_field_display()方法
                                                                        # restframework源码内部会判断"()"是否该添加

    m2m查询数据

    # m2m字段取数据,需要自定义方法,这里使用SerializerMethodField,方法名称get_field(),这里定义get_recommends()方法。
        # class Meta中的fields需要明确字段值,字段值必须与通过这里使用SerializerMethodField()生成的实例对象名相等。
        recommends = serializers.SerializerMethodField()

    def get_recommends(self, obj):
    queryset = obj.recommend_course.all()
    return [{"id":row.id, "title":row.title} for row in queryset]

    # 二者与class Meta同级,直接定义在class下

    反向查询数据

    chapter = serializers.SerializerMethodField()
    
    def get_chapter(self, obj):
            queryset = obj.course.chapter_set.all()
            return [{"id":row.id, "name":row.name} for row in queryset]
    
    # 二者与class Meta同级,直接定义在class下

    depth定义返回的数据深浅

      因为接口返回的数据包含外键,所以外键的值为整数,默认depth=0,如果设置depth=1,那么外键的值会从整数变为外键值在关联表中对应的数据,如果外键关联表中返回数据中让然包含外键,并且depth=2或者更大,那么这个外键值会像一级外键一样,返回关联表对应的数据。

  • 相关阅读:
    使用Fiddler抓包(手机端app)
    IE浏览器跳转url正常,谷歌浏览器跳转报403状态
    书签
    工作记录
    MySQL索引、锁和优化
    Pytorch-张量的创建与使用方法
    网络请求
    数据挖掘的五大流程
    uni开启下拉刷新
    uni-app中的tabBar配置
  • 原文地址:https://www.cnblogs.com/ttyypjt/p/10999458.html
Copyright © 2020-2023  润新知