一、创建序列化模型文件serializers.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,需要单独配置。另外,如果需要进行字段反向查询,也需要单独设置。
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或者更大,那么这个外键值会像一级外键一样,返回关联表对应的数据。