读了我这篇博客, 你会刷新对面对对象的认知, 之前的面对对象都是 LJ~~~
表结构
- class Publisher(models.Model):
- name = models.CharField(max_length=32)
- def __str__(self):
- return self.name
- class Author(models.Model):
- name = models.CharField(max_length=32)
- def __str__(self):
- return self.name
- class Book(models.Model):
- title = models.CharField(max_length=32)
- pub_date = models.DateField()
- CHOICES = ((1, 'Python'), (2, 'Go'), (3, 'linux'))
- category = models.IntegerField(choices=CHOICES)
- publisher = models.ForeignKey(to='Publisher', on_delete=models.CASCADE)
- authors = models.ManyToManyField(to='Author')
- def __str__(self):
- return self.title
原路由:
- urlpatterns = [
- url(r'^admin/', admin.site.urls),
- url(r'^books/$', views.BookListView.as_view()),
- url(r'book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
- url(r'^publishers/$', views.PublisherView.as_view()),
- url(r'publishers/(?P<pk>\d+)$', views.PublisherDetailView.as_view()),
- ]
原始版:
获取出版社信息
- # 获取出版社信息
- class PublisherView(APIView):
- """使用 Django REST framework 内置的序列化"""
- def get(self,request):
- """Json 格式返回所有的书籍信息"""
- queryset = models.Publisher.objects.all()
- ser_obj = ModelPublisherSerlizer(queryset, many=True)
- return Response(ser_obj.data)
- def post(self, request):
- ser_obj = ModelPublisherSerlizer(data=request.data)
- if ser_obj:
- ser_obj.save()
- return Response('ok')
- else:
- return Response(ser_obj.errors)
获取具体某个出版社信息 查 改 删 -->
- # 获取具体某个出版社信息
- class PublisherDetailView(APIView):
- def get(self,pk):
- publisher_ob = models.Publisher.objects.filter(pk=pk)
- publisher_obj = models.Publisher.objects.filter(pk=pk).first()
- print("publisher_ob", publisher_ob, "publisher_obj", publisher_obj)
- if publisher_obj:
- ser_obj = ModelPublisherSerlizer(publisher_obj)
- return Response(ser_obj.data)
- else:
- return Response("无效的 id")
- def put(self, request, pk):
- publisher_obj = models.Publisher.objects.filter(pk=pk).first()
- if publisher_obj:
- ser_obj = ModelPublisherSerlizer(instance=publisher_obj, data=request.data, partial=True)
- if ser_obj.is_valid():
- ser_obj.save()
- return Response(ser_obj.data)
- else:
- return Response(ser_obj.errors)
- else:
- return Response("没有这本书")
- def delete(self,pk):
- publisher_obj = models.Publisher.objects.filter(pk=pk)
- if publisher_obj:
- publisher_obj.delete()
- return Response("删除成功")
- else:
- return Response("没有这本书")
进化版:
把出版社相关信息封装起来
- class CemericView(APIView):
- """视图中可能用到的配置和方法封装起来"""
- queryset = None
- serializer_class = None
- def get_queryset(self):
- # 让每次请求来的时候都先查一次数据
- return self.queryset.all()
- class ListMinxin(object):
- def get(self, request):
- queryset = self.get_queryset()
- ser_obj = self.serializer_class(queryset, many=True)
- return Response(ser_obj.data)
- class CreateMixin(object):
- def post(self, request):
- ser_obj = self.serializer_class(data=request.data)
- if ser_obj:
- ser_obj.save()
- return Response('ok')
- else:
- return Response(ser_obj.errors)
- # 获取出版社信息
- class PublisherView(CemericView, ListMinxin, CreateMixin):
- queryset = models.Publisher.objects.all()
- serializer_class = ModelPublisherSerlizer
超级进化版:
把某个出版社的信息也封装起来
- class GemericView(APIView):
- """视图中可能用到的配置和方法封装起来"""
- queryset = None
- serializer_class = None
- def get_queryset(self):
- # 让每次请求来的时候都先查一次数据
- return self.queryset.all()
- def get_obj(self, request, pk, *args, **kwargs):
- return self.get_queryset().filter(pk=pk).filter(pk=pk).first()
- class ListMinxin(object):
- def get(self, request):
- queryset = self.get_queryset()
- ser_obj = self.serializer_class(queryset, many=True)
- return Response(ser_obj.data)
- class CreateMixin(object):
- def post(self, request):
- ser_obj = self.serializer_class(data=request.data)
- if ser_obj.is_valid():
- ser_obj.save()
- return Response('ok')
- else:
- return Response(ser_obj.errors)
- # 获取出版社信息
- class PublisherView(GemericView, ListMinxin, CreateMixin):
- queryset = models.Publisher.objects.all()
- serializer_class = ModelPublisherSerlizer
- class RetrieveMixin(object):
- def get(self, request, pk, *args, **kwargs):
- obj = self.get_obj(request, pk, *args, **kwargs)
- if obj:
- ser_obj = self.serializer_class(obj)
- return Response(ser_obj.data)
- else:
- return Response("无效的 id")
- class UpdateMixin(object):
- def put(self, request, pk, *args, **kwargs):
- obj = self.get_obj(request, pk, *args, **kwargs)
- if obj:
- ser_obj = ModelPublisherSerlizer(instance=obj, data=request.data, partial=True)
- if ser_obj.is_valid():
- ser_obj.save()
- return Response(ser_obj.data)
- else:
- return Response(ser_obj.errors)
- else:
- return Response("没有这本书")
- class DelMixin(object):
- def delete(self, request, pk, *args, **kwargs):
- obj = self.get_obj(request, pk, *args, **kwargs)
- print(obj)
- # print(obj.filter(pk = pk))
- if obj:
- obj.delete()
- return Response("删除成功")
- else:
- return Response("没有这本书")
- # 获取具体某个出版社信息
- class PublisherDetailView(GemericView, RetrieveMixin, UpdateMixin, DelMixin):
- queryset = models.Publisher.objects.all()
- serializer_class = ModelPublisherSerlizer
如果在写一个 API 的话 只需要 3 行代码,
但是 封装的代码好像有点多, 继承关系有点乱,
其实框架本身提供了内置方法,
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
注意: 单纯的导入 不能成功, 因为 此方法中不是以 get ,post 等命名的, 导致 MVC 模型中 as.view(), 找不到 请求的方式, 需要 对 这些方法进行进一步封装
就有了下面的内置方法
- from rest_framework.generics import ListCreateAPIView,RetrieveDestroyAPIView
- # 这个包里里面 封装了 各种用于 API 开发的浏览器 请求方式, 及组合方式, 直接调用即可
一共 7 行 代码解决
- from rest_framework.generics import ListCreateAPIView, RetrieveDestroyAPIView
- # 获取出版社信息
- class PublisherView(ListCreateAPIView):
- queryset = models.Publisher.objects.all()
- serializer_class = ModelPublisherSerlizer
- # 获取具体某个出版社信息
- class PublisherDetailView(RetrieveDestroyAPIView):
- queryset = models.Publisher.objects.all()
- serializer_class = ModelPublisherSerlizer
究极进化版:
上面超级进化版 一张表要写两个视图 定义 queryset 和 serializer_class 重复,
而且 路由也需要重复, 显然, 究极进化是不允许的~~
重写了 as_view() 方法, 实现了根据请求的方法执行具体的类方法
路由注册的时候, 利用 actions 参数, 实现路由的定向分发 而不是简单的 反射
- url(r'authors/$', views.AuthorViewSet.as_view(actions={'get': 'list', 'post': 'create'})), # 作者列表
- url(r'authors/(?P<pk>\d+)/$', views.AuthorViewSet.as_view(
- actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})
- ), # 作者详情
路由都重复写两条:
还可以利用内置的 DefaultRouter 来实现路由的注册
- from rest_framework.routers import DefaultRouter
- router = DefaultRouter()
- router.register('authors', views.AuthorViewSet)
- urlpatterns += router.urls
- from rest_framework.viewsets import ModelViewSet
- class AuthorViewSet(ModelViewSet):
- """
- list()
- create()
- retrieve()
- update()
- destroy()
- """
- queryset = models.Author.objects.all()
- serializer_class = AuthorModelSerializer
总结:
建议用以下两种方式
来源: https://www.cnblogs.com/konghui/p/10268393.html