• django DRF增删改查查


     
    

            使用Django的DRF框架,基于restful接口规范的增删改查(查所有)查(查一个)操作,一般默认有如下规范:

    /book/  GET 查看所有资源,返回所有资源; /book/  POST 添加资源,返回添加的资源;

    /book/1 GET 查看某一个资源,返回这一个资源;

    /book/1 PUT 编辑某一个资源,返回编辑之后的这个资源;

    /book/1 DELETE 删除某一个资源,返回空;

    一、基于APIView的接口实现

    1、urls.py

    1. urlpatterns = [
    2. path('sers/book/', views.BookView.as_view()),
    3. re_path('sers/book/(\d+)', views.BookDetailView.as_view()),
    4. ]

    2、models.py

    1. class Book(models.Model):
    2. title = models.CharField(verbose_name="书籍名称",max_length=32)
    3. price = models.IntegerField(verbose_name="价格",null=True) #如果不设置null,数据库默认是不能为空的;
    4. pub_data = models.DateField(verbose_name="出版时间")

    3、views.py

    1. # 针对模型设计序列化器
    2. class BookSerializers(serializers.Serializer):
    3. title = serializers.CharField(max_length=32)
    4. price = serializers.IntegerField(required=False)
    5. pub_data = serializers.DateField()
    6. # 字段名要和models中的名字一致,不然会报错,如果需要自定义需要通过如下方法:
    7. # data = serializers.DateTimeField(source="pub_data")
    8. # seve方法重写
    9. def create(self, validated_data):
    10. # 添加数据逻辑
    11. new_book = Book.objects.create(**self.validated_data)
    12. return new_book
    13. def update(self, instance, validated_data):
    14. # 更新逻辑
    15. Book.objects.filter(pk=instance.pk).update(**validated_data)
    16. # 针对更新加的两句话,区分instance
    17. updated_book = Book.objects.get(pk=instance.pk)
    18. return updated_book
    19. class BookView(APIView):
    20. def get(self,request):
    21. '''查看所有书籍'''
    22. book_list = models.Book.objects.all()
    23. # 构建序列化器对象
    24. serializer = BookSerializers(instance=book_list,many=True)
    25. return Response(serializer.data)
    26. def post(self,request):
    27. '''添加书籍'''
    28. # 获取请求数据
    29. data = request.data
    30. # 构建序列化器对象
    31. serializer = BookSerializers(data=request.data)
    32. # 校验数据:返回布尔值,serializer.validated_data ,在这里校验,如果不通过,保存到这里serializer.errors
    33. if serializer.is_valid():
    34. # 数据校验通过,将数据插入到数据库中
    35. # new_book= Book.objects.create(**serializer.validated_data)
    36. serializer.save()
    37. return Response(serializer.data)
    38. else:
    39. # 校验失败
    40. return Response(serializer.errors)
    41. class BookDetailView(APIView):
    42. def get(self,request,id):
    43. '''查某一个'''
    44. book = Book.objects.get(pk=id) #模型类对象和queryset对象
    45. serializer = BookSerializers(instance=book,many=False)
    46. return Response(serializer.data)
    47. def put(self,request,id):
    48. '''编辑某一个数据,更新数据'''
    49. # 找到需要编辑的对象
    50. up_book = Book.objects.get(pk=id)
    51. # 构建序列化对象,这里instance和data这两个参数都要有;
    52. serializer = BookSerializers(instance=up_book,data=request.data)
    53. # 数据校验,反序列化
    54. if serializer.is_valid():
    55. serializer.save()
    56. return Response(serializer.data)
    57. else:
    58. return Response(serializer.errors)
    59. def delete(self,request,id):
    60. # 删除
    61. Book.objects.get(pk=id).delete()
    62. return Response()

    4、针对views.py中的模型序列化器,还有以下更简便的写法,这个里面的create和update方法都自动被写好了,不用自己定义,自己只设置字段就可以了。

    1. class BookSerializers(serializers.ModelSerializer):
    2. class Meta:
    3. model = Book
    4. fields = "__all__"
    5. # fields = ["title", "price"]
    6. # exclude = ["pub_date"]

    二、基于GenericAPIView的接口实现

    GenericAPIView是继承的APIView,然后又实现了一些自定义的方法。
    

    1、urls.py

    1. path('sers/publish/', views.PublishView.as_view()),
    2. # ?p 有名分组,这样写之后会行成 pk=\d 的形式
    3. re_path('sers/publish/(?P\d+)', views.PublishDetailView.as_view()),

    2、models.py

    1. class Publish(models.Model):
    2. name = models.CharField(max_length=32)
    3. addr = models.CharField(max_length=32)

    3、views.py

    1. from rest_framework.generics import GenericAPIView
    2. class PublishSerializers(serializers.ModelSerializer):
    3. class Meta:
    4. model = Publish
    5. fields = "__all__"
    6. class PublishView(GenericAPIView):
    7. # 定义2个类全局变量;以后复用这个类的时候,只改两个全局变量;
    8. queryset = Publish.objects.all()
    9. serializer_class = PublishSerializers
    10. def get(self,request):
    11. '''查看所有'''
    12. serializer = self.get_serializer(instance=self.get_queryset(),many=True)
    13. return Response(serializer.data)
    14. def post(self,request):
    15. '''添加'''
    16. serializer = self.get_serializer(data=request.data)
    17. if serializer.is_valid():
    18. serializer.save()
    19. return Response(serializer.data)
    20. else:
    21. return Response(serializer.errors)
    22. class PublishDetailView(GenericAPIView):
    23. # 定义2个类全局变量;以后复用这个类的时候,只改两个全局变量;
    24. queryset = Publish.objects.all()
    25. serializer_class = PublishSerializers
    26. def get(self,request,pk): # pk要对应URL中,pk在源码中可以改,不建议改;
    27. '''查一个'''
    28. serializer = self.get_serializer(instance=self.get_object(), many=False)
    29. return Response(serializer.data)
    30. def put(self,request,pk):
    31. '''编辑'''
    32. serializer = self.get_serializer(instance=self.get_object(),data=request.data)
    33. if serializer.is_valid():
    34. serializer.save()
    35. return Response(serializer.data)
    36. else:
    37. return Response(serializer.errors)
    38. def delete(self,request,pk):
    39. '''删除'''
    40. self.get_object().delete()
    41. return Response()

    三、基于Mixin的接口实现 

    1、urls.py

    1. path('sers/publish/', views.PublishView.as_view()),
    2. # ?p 有名分组,这样写之后会行成 pk=\d 的形式
    3. re_path('sers/publish/(?P\d+)', views.PublishDetailView.as_view()),

    2、models.py

    1. class Publish(models.Model):
    2. name = models.CharField(max_length=32)
    3. addr = models.CharField(max_length=32)

    3、 views.py

    1. from rest_framework.generics import GenericAPIView
    2. from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin
    3. class PublishSerializers(serializers.ModelSerializer):
    4. class Meta:
    5. model = Publish
    6. fields = "__all__"
    7. class PublishView(ListModelMixin,CreateModelMixin,GenericAPIView):
    8. # 定义2个类全局变量;以后复用这个类的时候,只改两个全局变量;
    9. queryset = Publish.objects.all()
    10. serializer_class = PublishSerializers
    11. def get(self,request):
    12. '''查看所有'''
    13. # list()方法来源于父类ListModelMixin中的方法
    14. return self.list(request)
    15. def post(self,request):
    16. '''添加'''
    17. # create()方法来源于父类CreateModelMixin中的方法
    18. return self.create(request)
    19. class PublishDetailView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
    20. # 定义2个类全局变量;以后复用这个类的时候,只改两个全局变量;
    21. queryset = Publish.objects.all()
    22. serializer_class = PublishSerializers
    23. def get(self,request,pk):
    24. '''查一个'''
    25. # retrieve()方法来源于父类RetrieveModelMixin中的方法
    26. return self.retrieve(request,pk)
    27. def put(self,request,pk):
    28. '''编辑'''
    29. # update()方法来源于父类UpdateModelMixin中的方法
    30. return self.update(request,pk)
    31. def delete(self,request,pk):
    32. '''删除'''
    33. # destroy()方法来源于父类DestroyModelMixin中的方法
    34. return self.destroy(request,pk)

    4、对于views.py中,Mixin类再封装的操作

    1. # ListCreateAPIView 封装了ListModelMixin,CreateModelMixin,GenericAPIView三个类,和get/post两个方法;
    2. # RetrieveUpdateDestroyAPIView 封装了RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView四个类,实现了get/put/delete三个方法;
    3. from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
    4. class PublishSerializers(serializers.ModelSerializer):
    5. class Meta:
    6. model = Publish
    7. fields = "__all__"
    8. class PublishView(ListCreateAPIView):
    9. # get/post方法全部在ListCreateAPIView中,不用自己写;
    10. queryset = Publish.objects.all()
    11. serializer_class = PublishSerializers
    12. # 有的情况下,一个接口不见得会全部要增删改查查,也许只有查看和编辑,不允许删除,还有类可以继承RetrieveUpdateAPIView
    13. class PublishDetailView(RetrieveUpdateDestroyAPIView):
    14. # get/put/delete方法全部在RetrieveUpdateDestroyAPIView中,不用自己写;
    15. queryset = Publish.objects.all()
    16. serializer_class = PublishSerializers

    四、基于ViewSet的接口实现,涉及到GenericViewSet和ModelViewSet

    ViewSet是DRF的一个类,ViewSet继承了ViewSetMixin, views.APIView 由于路由的分发原则是按照请求方式分发的,dispatch里面进行分发; 之前五个方法都是写了2个类,现在要二合一; 必须要修改分发机制,不然五个方法没有办法写在一个类里面; ViewSetMixin重塑了分发机制,不用自己写。

    1、urls.py

    1. path('sers/publish/', views.PublishView.as_view({"get":"list","post":"create"})),
    2. re_path('sers/publish/(?P\d+)', views.PublishView.as_view({"get":"retrieve","put":"update","delete":"destroy"})),

    针对上面的路由写法,也可以通过路由组件完成:

    1. # 路由组件
    2. from rest_framework import routers
    3. router=routers.DefaultRouter()
    4. router.register("publish",views.PublishView)
    5. # 加在最后面,列表外面
    6. urlpatterns += router.urls

    2、models.py

    1. class Publish(models.Model):
    2. name = models.CharField(max_length=32)
    3. addr = models.CharField(max_length=32)

    3、views.py

    第一种方法:

    1. from rest_framework.viewsets import GenericViewSet
    2. from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin
    3. class PublishSerializers(serializers.ModelSerializer):
    4. class Meta:
    5. model = Publish
    6. fields = "__all__"
    7. class PublishView(GenericViewSet,ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin):
    8. queryset = Publish.objects.all()
    9. serializer_class = PublishSerializers

    第二种方法:

    通过ModelViewSet高度封装 ,ModelViewSet里面封装了GenericViewSet,ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin 

    1. from rest_framework.viewsets import ModelViewSet
    2. class PublishSerializers(serializers.ModelSerializer):
    3. class Meta:
    4. model = Publish
    5. fields = "__all__"
    6. class PublishView(ModelViewSet):
    7. queryset = Publish.objects.all()
    8. serializer_class = PublishSerializers

     

  • 相关阅读:
    Java新领域—设计
    JavaEE UDP报文结构
    设计模式——装饰器模式
    【mysql】 bash: mysql: command not found
    安泰电压放大器在低频探测天线技术研究中的应用
    MECT4CNER 代码遇到的问题
    Qt中 QMap 类、QHash 类、QVector 类详解
    java毕业生设计学习类视频网计算机源码+系统+mysql+调试部署+lw
    【Axios封装示例Vue2】
    58欧氏空间05——实对称矩阵的正交相似对角化
  • 原文地址:https://blog.csdn.net/weixin_47401101/article/details/134401830