[django]梳理drf知识点
生活随笔
收集整理的這篇文章主要介紹了
[django]梳理drf知识点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
要實現的功能
idc_list/get 列出所有post 創建一個idcidc_detail/1/get 獲取一個idcput 修改一個idcdelete 刪除一個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 = IdcSerializerdef 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 = IdcSerializerdef 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 IdcViewsetroute = 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種
提交數據,數據驗證流程
提交一次數據流程
子表展示主表的字段(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- 機柜APPfrom idcs.models import Idcclass 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/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時修改
- validate_vendor_name時修改
- validate時修改
- create時候修改
本來想在創建型號時候指定制造商, 如果制造商不存在,則創建.如果存在則關聯
{"model_name": "mi8","vender": "xiaomi" } class ProductModelSerializer(serializers.ModelSerializer):class Meta:model = ProductModelfields = "__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_objreturn 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']}>- 下面這種寫法也報錯
解決這個問題
1.序列化時外鍵是字符串
2.和primarykey形成對比
子表顯示外鍵
方法1: 繼承ModelSerializer
class ManufacturerSerializer(serializers.ModelSerializer):class Meta:model = Manufacturerfields = "__all__"def validate_vender_name(self, data):return data.upper()class ProductModelSerializer(serializers.ModelSerializer):class Meta:model = Manufacturerfields = "__all__"方法2: PrimaryKeyRelatedField
class ManufacturerSerializer(serializers.ModelSerializer):class Meta:model = Manufacturerfields = "__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 = Manufacturerfields = "__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 resdef validate(self, attrs):print(attrs) # OrderedDict([('model_name', 'mi10'), ('vender', <Manufacturer: xiaomi>)])return attrsdef 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賦給了venderdef validate(self, attrs):print(attrs) # OrderedDict([('model_name', 'mi11'), ('vender', <Manufacturer: xiaomi>)])return attrsdef 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 attrsdef 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:passreturn attrsdef 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 attrsdef 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 Viewfrom 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 viewsetsfrom .models import Idc from .serializers import IdcSerializer from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParserfrom rest_framework import mixins, genericsclass IdcView(viewsets.ModelViewSet):queryset = Idc.objects.all()serializer_class = IdcSerializerclass IdcView_v7(viewsets.GenericViewSet,mixins.ListModelMixin,mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin):queryset = Idc.objects.all()serializer_class = IdcSerializerclass IdcView_v6(generics.ListCreateAPIView, generics.RetrieveUpdateDestroyAPIView):queryset = Idc.objects.all()serializer_class = IdcSerializerclass IdcViewDetail_v6(generics.RetrieveUpdateDestroyAPIView):queryset = Idc.objects.all()serializer_class = IdcSerializerclass IdcView_v5(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):queryset = Idc.objects.all()serializer_class = IdcSerializerdef 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 = IdcSerializerdef 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_patternsfrom 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
route.register函數的base_name參數定制url(默認是modelname為準)
譬如我寫了2個viewset,針對的是相同的model和serializer
class ServerAutoReportViewset(viewsets.ReadOnlyModelViewSet):queryset = Server.objects.all()serializer_class = ServerSerializerclass ServerViewset(viewsets.ReadOnlyModelViewSet):queryset = Server.objects.all()serializer_class = ServerSerializer默認展示的時候以model名字來展示
否則2個viewset只顯示第一個.
drf繼承圖
轉載于:https://www.cnblogs.com/iiiiiher/p/9892809.html
總結
以上是生活随笔為你收集整理的[django]梳理drf知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 脱壳
- 下一篇: CHD6.3.1部署文档