[django]梳理drf知识点

要实现的功能

idc_list/
    get  列出所有
    post 创建一个idc

idc_detail/1/
    get    获取一个idc
    put    修改一个idc
    delete 删除一个idc

一般url是这样处理的

    url("^idcs/$", idc_list),
    url("^idcs/(?P<pk>[0-9]+)/$", idc_detail)

从后端取数据到前端有哪些流程? 什么叫序列化? 什么叫反序列化?

序列化&反序列化

对象 -> 字符串 是序列化 json.dump()
字符串->对象 是反序列化 json.parse()


3件大事

1.取数据

2.序列化

3.方法绑定 asview方法搞定

GenericAPIView2个get冲突,必须写2个view,而viewset重写了as_view方法,解决了这个url问题

- GenericAPIView不能把所有的都混在一起,必须分2个view写

class IdcList_v4(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class IdcDetail_v4(generics.GenericAPIView, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

1个资源为什么要2个url? viewset可以解决idc_list和idc_detail 1个资源两个url问题

- viewset可以这样写

class IdcListViewset_v6(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin,
                        mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

巧妙的写2个绑定关系,都绑定到一个试图上

    path('idcs/', views.IdcListViewset.as_view({'get': 'list', 'post': 'create'}), name='idc_list'),
    path('idcs/<int:pk>/', views.IdcDetailViewset.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}),

最终被router彻底解决

rom rest_framework.routers import DefaultRouter
from idcs.views import IdcViewset

route = DefaultRouter()
route.register('idcs', IdcViewset)


urlpatterns = [
    path('', include(route.urls)),
]

mixin做什么事情?

1,取数据
2.序列化 --这两项mixins.RetrieveModelMixin做的实行

3.绑定方法:  as_view做点事情
取数据    序列化    render                   方法绑定
mixin    mixin     APIView+Response干了     as_view干了
                   存数据: IdcSerilizer(data=request.data)
                   取数据: Response(IdcSerilizer(idc.data))

3种as_view

  • as_view的功能

  • as_view的内置3种

1. as_view()  base  
2. as_view()  restframework  重写了as_view方法
3. as_view()  Viewset            重写了as_view方法
- 用的的是 1. as_view()  base  
class IdcList_v3(APIView):
    def get(self, request):
        return Response(IdcSerializer(Idc.objects.all().data, many=True))

    def post(self, request):
        serializer = IdcSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse("创建成功")
        return HttpResponse("创建失败")
- 用的是 2. as_view()  restframework
class IdcList_v5(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

- 用的是 3. as_view()  Viewset(要求绑定关系写到url里)

class IdcListViewset(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer
    path('idcs/', views.IdcListViewset.as_view({'get': 'list', 'post': 'create'}), name='idc_list'),
    path('idcs/<int:pk>/', views.IdcDetailViewset.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}),
         name='idc_detail'),

提交数据,数据验证流程

提交一次数据流程

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def to_internal_value(self, data):
        print('to_internal_value(data): ', data)
        return super(ManufacturerSerializer, self).to_internal_value(data)

    def validate_vender_name(self, data):
        print('validate_vender_name(data): ', data)
        return data

    def validate(self, attrs):
        print("validate验证(attrs): ", attrs)
        return attrs

    def create(self, validated_data):
        print('create(validated_data): ', validated_data)
        return Manufacturer.objects.create(**validated_data)
to_internal_value(data)     : <QueryDict: {'csrfmiddlewaretoken': ['bp0QXpil9GwXUDhKYO0ut03dr2C6YGVT12WWOGIV49z7QMEeZHRE5Qsz4DBE5tTt'], 'vender_name': ['dell'], 'tel': ['13111111111'], 'mail': ['xxx@foxmail.com'], 'remark': ['test']}>
validate_vender_name(data)  :  dell
validate验证(attrs)         :  OrderedDict([('vender_name', 'dell'), ('tel', '13111111111'), ('mail', 'xxx@foxmail.com'), ('remark', 'test')])
create(validated_data)      :  {'vender_name': 'dell', 'tel': '13111111111', 'mail': 'xxx@foxmail.com', 'remark': 'test'}

子表展示主表的字段(to_representation): 希望获取某个机柜时候,展示idc的id&name

注意: 从db取出数据到前端展示, 不经过validate和validate_data, 所以只能在to_representation处做.

- IDC APP
class Idc(models.Model):
    name = models.CharField(max_length=20)
    address = models.CharField(max_length=20)
    phone = models.CharField(max_length=20)
    letter = models.CharField(max_length=20)

    def __str__(self):
        return self.name


- 机柜APP

from idcs.models import Idc

class Cabinet(models.Model):
    "机柜模型"
    idc = models.ForeignKey(Idc, on_delete=models.CASCADE)
    name = models.CharField('机柜名称', max_length=40)

    def __str__(self):
        return self.name

默认是这样的, 看不出idc的名字

- 机柜序列化类to_representation,抛给前端最后一步来动刀

class CabinetSerializer(serializers.Serializer):
    "机柜序列化类"
    idc = serializers.PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all())
    name = serializers.CharField(max_length=20)

    def create(self, validated_data):
        return Cabinet.objects.create(**validated_data)

    # instance是一个机柜的obj
    def to_representation(self, instance):
        print(instance)
        print(type(instance))     # <class 'cabinet.models.Cabinet'>
        print(instance.idc)
        print(type(instance.idc)) # <class 'idcs.models.Idc'>
        res = super(CabinetSerializer, self).to_representation(instance)
        print(res) # OrderedDict([('idc', 1), ('name', '1-2')])
        res['idc'] = {
            'name': instance.idc.name,
            'phone': instance.idc.phone
        }
        return res

最接近前端的to_representation/to_internal_value处理后的OrderedDict可以k['v']形式取值

也可以通过点的方式取

OrderedDict([('idc', 1), ('name', '1-2')])


        res = super(CabinetSerializer, self).to_representation(instance)
        print(res) # OrderedDict([('idc', 1), ('name', '1-2')])
        res['idc'] = {
            'name': instance.idc.name,
            'phone': instance.idc.phone
        }

制造商名称大写: 入库时4个节点可以修改

validate时修改方便点.

  • to_internal_value时修改
class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def to_internal_value(self, data):
        print('data: ', data)
        res = super(ManufacturerSerializer, self).to_internal_value(data)
        print('res: ', res)
        res['vendor_name'] = res['vendor_name'].upper()
        return res



data:  <QueryDict: {'csrfmiddlewaretoken': ['B27kAKtSmrRDmIUco8umj5nFbsdcnOOWVdlBRJ7DgRfJjnmSh7YINSk5nXNbYmoD'], 'vendor_name': ['cs7'], 'tel': ['13333333333'], 'mail': ['ihorse@foxmail.com'], 'remark': ['cs7']}>
res:  OrderedDict([('vendor_name', 'cs7'), ('tel', '13333333333'), ('mail', 'ihorse@foxmail.com'), ('remark', 'cs7')])
  • validate_vendor_name时修改
class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def validate_vendor_name(self, value):
        print('value: ',value)
        return value.upper()

cs6
  • validate时修改
class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"


    def validate(self, attrs):
        print('validate(attrs): ', attrs)
        attrs['vendor_name'] = attrs['vendor_name'].upper()
        return attrs


validate(attrs):  OrderedDict([('vendor_name', 'cs4'), ('tel', '13444444444'), ('mail', 'ihorse@foxmail.com'), ('remark', 'cs4')])
  • create时候修改
class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def create(self, validated_data):
        print('create(validated_data): ',validated_data)
        validated_data['vender_name'] = validated_data['vender_name'].upper()
        return Manufacturer.objects.create(**validated_data)

create(validated_data):  {'vender_name': 'cs8', 'tel': '13444444444', 'mail': 'ihorse@foxmail.com', 'remark': None}

本来想在创建型号时候指定制造商, 如果制造商不存在,则创建.如果存在则关联

{
    "model_name": "mi8",
    "vender": "xiaomi"
}

class ProductModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductModel
        fields = "__all__"

    def to_internal_value(self, data):
        print(data)
        res = super(ProductModelSerializer, self).to_representation(data)
        print(2)
        try:
            manufacturer_obj = Manufacturer.objects.get(vender_name__exact=data['vender'])
        except Manufacturer.DoesNotExist:
            manufacturer_obj = Manufacturer.objects.create(vender_name=data['vender'])
        res['vender'] = manufacturer_obj
        return res

    # def validate_vender(self, value): #根本都走不到这里.在to_internal_value时字段serializer时候就报错了.
    #     "制造商验证"
    #     print('value: ', value, type(value))
    #     try:
    #         return Manufacturer.objects.get(vender_name__exact=value)
    #     except Manufacturer.DoesNotExist:
    #         print(type(value))
    #         return Manufacturer.objects.create(vender_name=value)

    # def validate(self, attrs):
    #     "主表验证子表唯一性"
    #     manufacturer_obj = attrs['vender']
    #     try:
    #         manufacturer_obj.productmodel_set(model_name__exact=attrs['model_name'])
    #     except ProductModel.DoesNotExist:
    #         return attrs

<QueryDict: {'csrfmiddlewaretoken': ['afVAElHU9XdiA4J41r8Kiycs2uLqRwy9kyTK1tpyIuaNw5P6bg3yFf03fSmS3vwJ'], 'model_name': ['R710'], 'vender': ['1']}>
  • 下面这种写法也报错

class ProductModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductModel
        fields = "__all__"

    def validate_manufacturer(self, value):
        "制造商唯一性验证"
        try:
            return Manufacturer.objects.get(vendor_name__exact=value)
        except Manufacturer.DoesNotExist:
            return self.create_manufacturer(value)

    def create_manufacturer(self, vendor_name):
        "创建制造商"
        return Manufacturer.objects.create(vendor_name=vendor_name)

    def validate(self, attrs):
        "制造商下型号唯一性验证"
        manufacturer_obj = attrs["manufacturer"]
        try:
            # 如果存在则获取索引
            # 如果不存在则创建并获取索引
            attrs["model_name"] = manufacturer_obj.productmodel_set.get(model_name__exact=attrs["model_name"])
        except ProductModel.DoesNotExist:
            attrs["model_name"] = self.create_product_model(manufacturer_obj, attrs["model_name"])
        return attrs

解决这个问题

1.序列化时外键是字符串
2.和primarykey形成对比

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"


class ProductModelSerializer(serializers.Serializer):
    # class Meta:
    #     model = ProductModel
    #     fields = "__all__"
    model_name = serializers.CharField(required=True)
    vender = serializers.CharField(required=True)

    def validate_vender(self, value):
        print(value)
        "制造商唯一性验证"
        try:
            return Manufacturer.objects.get(vender_name__exact=value)
        except Manufacturer.DoesNotExist:
            return self.create_manufacturer(value)

    def create_manufacturer(self, vender_name):
        "创建制造商"
        return Manufacturer.objects.create(vender_name=vender_name)

    def validate(self, attrs):
        "制造商下型号唯一性验证"
        print(attrs)
        manufacturer_obj = attrs["vender"]
        try:
            # 如果存在则获取索引
            # 如果不存在则创建并获取索引
            attrs["model_name"] = manufacturer_obj.productmodel_set.get(model_name__exact=attrs["model_name"])
        except ProductModel.DoesNotExist:
            # attrs["model_name"] = self.create_product_model(manufacturer_obj, attrs["model_name"])
            pass
        return attrs

    def create(self, validated_data):
        print(validated_data) # {'model_name': 'mi10', 'vender': <Manufacturer: xiaomi>}
        "创建型号"
        return ProductModel.objects.create(**validated_data)

子表显示外键

方法1: 继承ModelSerializer

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def validate_vender_name(self, data):
        return data.upper()


class ProductModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = Manufacturer
        fields = "__all__"

方法2: PrimaryKeyRelatedField

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def validate_vender_name(self, data):
        return data.upper()


class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.PrimaryKeyRelatedField(many=False, queryset=Manufacturer.objects.all())

    def create(self, validated_data):
        ProductModel.objects.create(**validated_data)

方法3:

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = "__all__"

    def validate_vender_name(self, data):
        return data.upper()

1.判断制造商是否存在: to_internal_value节点实现

class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)

    def to_internal_value(self, data):
        print(data)
        res = super(ProductModelSerializer, self).to_internal_value(data)
        print(res) # OrderedDict([('model_name', 'mi10'), ('vender', 'xiaomi')])
        try:
            res['vender'] = Manufacturer.objects.get(vender_name__exact=res['vender'])
        except Manufacturer.DoesNotExist:
            res['vender'] = Manufacturer.objects.create(vender_name=res['vender'])
        print(res) # OrderedDict([('model_name', 'mi10'), ('vender', <Manufacturer: xiaomi>)])
        return res

    def validate(self, attrs):
        print(attrs) # OrderedDict([('model_name', 'mi10'), ('vender', <Manufacturer: xiaomi>)])
        return attrs

    def create(self, validated_data):
        return ProductModel.objects.create(**validated_data)

2.判断制造商是否存在: validate_vender节点实现

class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)

    def validate_vender(self, value):
        print(value)  # 'xiaomi'
        try:
            manufacturer_obj = Manufacturer.objects.get(vender_name__exact=value)
        except Manufacturer.DoesNotExist:
            manufacturer_obj = Manufacturer.objects.create(vender_name=value)
        return manufacturer_obj  # 相当于把manufacturer_obj赋给了vender

    def validate(self, attrs):
        print(attrs)  # OrderedDict([('model_name', 'mi11'), ('vender', <Manufacturer: xiaomi>)])
        return attrs

    def create(self, validated_data):
        return ProductModel.objects.create(**validated_data)

3.判断制造商是否存在: validate节点实现

class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)

    def validate(self, attrs):
        print(attrs)  # OrderedDict([('model_name', 'p1'), ('vender', 'google')])
        try:
            attrs['vender'] = Manufacturer.objects.get(vender_name__exact=attrs['vender'])
        except Manufacturer.DoesNotExist:
            attrs['vender'] = Manufacturer.objects.create(vender_name=attrs['vender'])
        print(attrs)  # OrderedDict([('model_name', 'p1'), ('vender', <Manufacturer: google>)])
        return attrs

    def create(self, validated_data):
        return ProductModel.objects.create(**validated_data)

方法4: 也可以在create时候实现

通过主表,验证子表字段的唯一性: 验证该型号已存在

方法1: 在to_internal验证

方法2: 在valida_filed验证

方法3: 在validate时候验证

class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)

    def validate(self, attrs):
        "制造商验证"
        print(attrs)  # OrderedDict([('model_name', 'p2'), ('vender', 'google')])
        try:
            attrs['vender'] = Manufacturer.objects.get(vender_name__exact=attrs['vender'])
        except Manufacturer.DoesNotExist:
            attrs['vender'] = Manufacturer.objects.create(vender_name=attrs['vender'])
        print(attrs)  # OrderedDict([('model_name', 'p2'), ('vender', <Manufacturer: google>)])

        "制造商下型号唯一性验证"
        try:
            attrs['vender'].productmodel_set.get(model_name__exact=attrs['model_name'])
            raise serializers.ValidationError("该型号已存在")
        except ProductModel.DoesNotExist:
            pass
        return attrs

    def create(self, validated_data):
        print(validated_data)  # OrderedDict([('model_name', 'p2'), ('vender', <Manufacturer: google>)])
        return ProductModel.objects.create(**validated_data)

方法4: 在create时候验证

class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)

    def validate(self, attrs):
        "制造商验证"
        print(attrs)  # OrderedDict([('model_name', 'p2'), ('vender', 'google')])
        try:
            attrs['vender'] = Manufacturer.objects.get(vender_name__exact=attrs['vender'])
        except Manufacturer.DoesNotExist:
            attrs['vender'] = Manufacturer.objects.create(vender_name=attrs['vender'])
        print(attrs)  # OrderedDict([('model_name', 'p2'), ('vender', <Manufacturer: google>)])

        return attrs

    def create(self, validated_data):
        print(validated_data)  # OrderedDict([('model_name', 'p2'), ('vender', <Manufacturer: google>)])
        "制造商下型号唯一性验证"
        try:
            validated_data['vender'].productmodel_set.get(model_name__exact=validated_data['model_name'])
            raise serializers.ValidationError("该型号已存在")
        except ProductModel.DoesNotExist:
            return ProductModel.objects.create(**validated_data)

继承逻辑关系图

drf的版本迭代

from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views.generic.base import View

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
from rest_framework import viewsets

from .models import Idc
from .serializers import IdcSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

from rest_framework import mixins, generics


class IdcView(viewsets.ModelViewSet):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer


class IdcView_v7(viewsets.GenericViewSet,
              mixins.ListModelMixin,
              mixins.CreateModelMixin,
              mixins.RetrieveModelMixin,
              mixins.UpdateModelMixin,
              mixins.DestroyModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer



class IdcView_v6(generics.ListCreateAPIView, generics.RetrieveUpdateDestroyAPIView):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer


class IdcViewDetail_v6(generics.RetrieveUpdateDestroyAPIView):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer


class IdcView_v5(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class IdcViewDetail_v5(generics.GenericAPIView,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class IdcView_v4(APIView):
    def get(self, request, *args, **kwargs):
        return Response(IdcSerializer(Idc.objects.all(), many=True).data)

    def post(self, request, *args, **kwargs):
        serializer = IdcSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('添加成功')
        return HttpResponse('验证失败')


class IdcViewDetail_v4(APIView):
    def get_object(self, pk):
        try:
            return Idc.objects.get(pk=pk)
        except Exception as e:
            return HttpResponse("无此记录")

    def get(self, request, pk, *args, **kwargs):
        return Response(IdcSerializer(self.get_object(pk)).data)

    def put(self, request, pk, *args, **kwargs):
        serializer = IdcSerializer(self.get_object(pk), data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('添加成功')
        return HttpResponse('验证失败')

    def delete(self, request, pk, *args, **kwargs):
        self.get_object(pk).delete()
        return HttpResponse('删除成功')


@api_view(['GET'])
def api_root(request, format=None, *args, **kwargs):
    return Response(
        {
            'idc-list': reverse('idcs:idc-list', request=request)
        })


@api_view(['GET', 'POST'])
def idc_list_v3(request):
    if request.method == "GET":
        return Response(IdcSerializer(Idc.objects.all(), many=True).data)
    elif request.method == "POST":
        serializer = IdcSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('添加成功')
        return HttpResponse('验证失败')


@api_view(['GET', 'PUT', 'DELETE'])
def idc_detail_v3(request, pk):
    try:
        idc = Idc.objects.get(pk=pk)
    except Exception as e:
        return "记录不存在"
    if request.method == "GET":
        return Response(IdcSerializer(idc).data)
    if request.method == "PUT":
        serializer = IdcSerializer(idc, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('修改成功')
        return HttpResponse('验证失败')
    if request.method == "DELETE":
        idc.delete()
        return HttpResponse('删除成功')


class IdcView_v2(View):
    def get(self, request):
        return HttpResponse(JSONRenderer().render(IdcSerializer(Idc.objects.all(), many=True).data))

    def post(self, request):
        serializer = IdcSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('添加成功')
        return HttpResponse('验证失败')


class IdcViewDetail_v2(View):
    def get_object(self, pk):
        try:
            return Idc.objects.get(pk=pk)
        except Exception as e:
            return HttpResponse("无此记录")

    def get(self, request, pk):
        return HttpResponse(JSONRenderer().render(IdcSerializer(self.get_object(pk))))

    def put(self, request, pk):
        idc = self.get_object(pk)
        serializer = IdcSerializer(idc, data=JSONParser().parse(request))
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('修改成功')
        return HttpResponse('验证失败')


def idc_list_v1(request):
    if request.method == "GET":
        return HttpResponse(JSONRenderer().render(IdcSerializer(Idc.objects.all(), many=True).data))
    elif request.method == "POST":
        serializer = IdcSerializer(data=JSONParser().parse(request))
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('添加成功')
        return HttpResponse('验证失败')


def idc_detail_v1(request, pk):
    try:
        idc = Idc.objects.get(pk=pk)
    except Exception as e:
        return HttpResponse("没有这个记录")

    if request.method == "GET":
        return HttpResponse(JSONRenderer().render(IdcSerializer(idc).data))
    elif request.method == "PUT":
        serializer = IdcSerializer(idc, data=JSONParser().parse(request))
        if serializer.is_valid():
            serializer.save()
            return HttpResponse('更新成功')
        return HttpResponse('验证失败')
    elif request.method == "DELETE":
        Idc.objects.get(pk=pk).delete()
        return HttpResponse('删除成功')
# @api_view(['GET', 'PUT'])
# def idc_list(request, *args, **kwargs):
#     if request.method == "GET":
#         queryset = Idc.objects.all()
#         serializer = IdcSerializer(queryset, many=True)
#         return Response(serializer.data)
#     elif request.method == "PUT":
#         serializer = IdcSerializer(request.data)
#         return HttpResponse("")

urls.py

from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateView
from rest_framework.routers import DefaultRouter
from rest_framework.urlpatterns import format_suffix_patterns

from idcs import views

# idc_list = views.IdcView.as_view({
#     'get': 'list',
#     'post': 'create'
# })
#
# idc_detail = views.IdcView.as_view({
#     'get': 'retrieve',
#     'put': 'update',
#     'delete': 'destroy'
# })

route = DefaultRouter()
route.register('idcs', views.IdcView)

app_name = 'idcs'
urlpatterns = [
    # path('', views.api_root),
    # path('idcs', idc_list, name='idc-list'),
    path('', include(route.urls)),
    # path('idcs/<int:pk>/', idc_detail, name='idc-detail'),
]
# urlpatterns = format_suffix_patterns(urlpatterns)

drf版本迭代总结

理解序列化和反序列化的本质
https://www.bilibili.com/video/av39886713?from=search&seid=17895786208711765947

python使用protobuf序列化数据:
https://blog.csdn.net/menghaocheng/article/details/80176763

序列化: 后端->前端
queryset -> serializer -> JSONRender -> 返回前端

反序列化:后端<-前端
queryset <- serializer <- JSONParse  <- 前端提交


ApiView:
    Response,不用JSONRender/JSONParser了
    有界面了

API_ROOT设置
url设置

IdcView_v4(APIView)
IdcViewDetail_v4(APIView)


IdcView_v5(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin)
IdcViewDetail_v5(generics.GenericAPIView,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin):
    不需要关心数据了, 只需绑定方法


IdcView_v6(generics.ListCreateAPIView, generics.RetrieveUpdateDestroyAPIView)
IdcViewDetail_v6(generics.RetrieveUpdateDestroyAPIView)
    不需要关心数据,不需要绑定方法,但还是有2个视图+2个url


IdcView_v7(viewsets.GenericViewSet,
              mixins.ListModelMixin,
              mixins.CreateModelMixin,
              mixins.RetrieveModelMixin,
              mixins.UpdateModelMixin,
              mixins.DestroyModelMixin)
    不需要关心数据,需要绑定url, 有1个视图了.


IdcView(viewsets.ModelViewSet)
    简化了写法.

                                    generics.ListCreateAPIView=generics.GenericAPIView+
                                                               mixins.ListModelMixin+
                                                               mixins.CreateModelMixin

viewsets.ModelViewSet -> viewsets.GenericViewSet -->  generics.GenericAPIView(viewset再此基础上又封装了2层)
                         mixins.ListModelMixin

route.register函数的base_name参数定制url(默认是modelname为准)

譬如我写了2个viewset,针对的是相同的model和serializer

class ServerAutoReportViewset(viewsets.ReadOnlyModelViewSet):
    queryset = Server.objects.all()
    serializer_class = ServerSerializer


class ServerViewset(viewsets.ReadOnlyModelViewSet):
    queryset = Server.objects.all()
    serializer_class = ServerSerializer

默认展示的时候以model名字来展示

否则2个viewset只显示第一个.

route.register('ServerAutoReport', ServerAutoReportViewset, base_name='ServerAutoReport')
route.register('Server', ServerViewset, base_name='Server')

drf继承图

原文地址:https://www.cnblogs.com/iiiiiher/p/9892809.html