昨日内容回顾

  1. 1. Serializer(序列化)
  2. 1. ORM对应的query_setORM对象转换成JSON格式的数据
  3. 1. 在序列化类中定义自定义的字段:SerializerMethodField
  4. 在类中定义 get_自定义字段名(self, obj)方法
  5. 2. read_only 只在显示(查询)时才会有效。
  6.  
  7. 2. 对前端POST过来的数据做有效性的校验
  8. 1. 一定要将数据以data=的形式传递到序列化类中!!!
  9. ser_obj = CommentSerializer(data=comment_data)
  10. 2. 判断数据是否有效
  11. ser_obj.is_valid(): 欠一个源码
  12. ser_obj.validated_data 中保存经过校验的有效数据
  13.  
  14. 3. 局部钩子
  15. 定义一个validate_字段名(self, value)
  16. 4. 全局钩子
  17. 定义一个validate方法
  18.  
  19. 3. .save()方法将符合要求的数据存入数据库
  20. 1. 本质上还是调用ORMcreate()方法
  21. 类名.objects.create(**ser_obj.validated_data)
  22.  
  23. 2. 超链接的序列化
  24. 1. 超连接字段的三个参数
  25. # 文章超链接序列化
  26. class ArticleHyperLinkedSerializer(serializers.HyperlinkedModelSerializer):
  27. # view_name参数 默认使用 表名-detail
  28. # lookup_url_kwarg参数 默认使用pk,指的是反向生成URL的时候 路由中的分组命名匹配的key
  29. # lookup_field参数 默认使用的pk, 指的是反向生成URL的时候, 路由中分组命名匹配的value
  30. school = serializers.HyperlinkedIdentityField(
  31. view_name='school-detail111',
  32. lookup_url_kwarg='name',
  33. lookup_field='school_name'
  34. )
  35. 2. 想要生成完整的超链接API,在序列化的时候还要传入 context={'request': request}
  36. ser_obj = app01_serializers.ArticleHyperLinkedSerializer(all_article, many=True, context={'request': request})
  37. 1. 想要生成相对路径
  38. context={'request': None}

一、Django REST framework 视图

DRF中的Request

在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等。

比如,区别于Django中的request从request.GET中获取URL参数,从request.POST中取某些情况下的POST数据。

在APIView中封装的request,就实现了请求数据的解析:

一般来说,GET请求的参数,通过request.query_params来获取。POST、PUT通过request.data来获取

但这也不是绝对的,提交类型不同,获取参数的方式也是不一样的。详情请参考:

https://www.cnblogs.com/xiao987334176/p/9401486.html#autoid-3-3-3

面向对象三大特性

封装

1. 把共有的数据当成一类物体的属性
2. 把共有的功能当成一类物体的方法

继承

1. 把共有的属性或方法抽离出来放到一个基类(父类)中

多态

1. 不同的物体调用同一个方法有不同的效果
比如:Python中数字的+和字符串的+,结果是不一样的。前者是计算,后者是拼接!

葫芦娃的故事

先来列举前5个娃,为啥是5个呢?到最后,你就知道了!

  1. class Wa1(object):
  2. name = "红娃"
  3.  
  4. def f1(self):
  5. print("力大无穷!")
  6.  
  7. class Wa2(object):
  8. name = '橙娃'
  9.  
  10. def f2(self):
  11. print('千里眼顺风耳!')
  12.  
  13. class Wa3(object):
  14. name = '黄娃'
  15.  
  16. def f3(self):
  17. print('钢筋铁骨!')
  18.  
  19. class Wa4(object):
  20. name = '绿娃'
  21.  
  22. def f4(self):
  23. print("会喷火!")
  24.  
  25. class Wa5(object):
  26. name = '青蛙'
  27.  
  28. def f5(self):
  29. print("会喷水!")

奇数娃,它继承了一娃,三娃,五娃的技能

偶数娃,它继承了二娃,四娃的技能

套娃,它继承了奇数娃,偶数娃的技能。也就是说,它拥有5个娃的技能

实例化3个角色,分别调用奇数娃,偶数娃,套娃的info方法

完整代码如下:

  1. class Wa1(object):
  2. name = "红娃"
  3.  
  4. def f1(self):
  5. print("力大无穷!")
  6.  
  7. class Wa2(object):
  8. name = '橙娃'
  9.  
  10. def f2(self):
  11. print('千里眼顺风耳!')
  12.  
  13. class Wa3(object):
  14. name = '黄娃'
  15.  
  16. def f3(self):
  17. print('钢筋铁骨!')
  18.  
  19. class Wa4(object):
  20. name = '绿娃'
  21.  
  22. def f4(self):
  23. print("会喷火!")
  24.  
  25. class Wa5(object):
  26. name = '青蛙'
  27.  
  28. def f5(self):
  29. print("会喷水!")
  30.  
  31. class Jishuwa(Wa1, Wa3, Wa5):
  32. name = '奇数娃'
  33.  
  34. def info(self):
  35. print("我是%s,我会:" %self.name)
  36. self.skill()
  37.  
  38. def skill(self): # 技能
  39. self.f1()
  40. self.f3()
  41. self.f5()
  42.  
  43. class Oushuwa(Wa2, Wa4):
  44. name = '偶数娃'
  45.  
  46. def info(self):
  47. print("我是%s,我会:" % self.name)
  48. self.skill()
  49.  
  50. def skill(self): # 技能
  51. self.f2()
  52. self.f4()
  53.  
  54. class Taowa(Jishuwa, Oushuwa):
  55. name = '套娃'
  56.  
  57. def info(self):
  58. print("我是{}, 我会:".format(self.name))
  59. self.skill()
  60.  
  61. def skill(self): # 技能
  62. Jishuwa.skill(self)
  63. Oushuwa.skill(self)
  64.  
  65. print('奇数娃'.center(20, '❆'))
  66. role1 = Jishuwa()
  67. role1.info()
  68.  
  69. print('偶数娃'.center(20, '❆'))
  70. role2 = Oushuwa()
  71. role2.info()
  72.  
  73. print('套娃'.center(20, '❆'))
  74. role3 = Taowa()
  75. role3.info()

执行输出:

  1. ❆❆❆❆❆❆❆❆奇数娃❆❆❆❆❆❆❆❆❆
  2. 我是奇数娃,我会:
  3. 力大无穷!
  4. 钢筋铁骨!
  5. 会喷水!
  6. ❆❆❆❆❆❆❆❆偶数娃❆❆❆❆❆❆❆❆❆
  7. 我是偶数娃,我会:
  8. 千里眼顺风耳!
  9. 会喷火!
  10. ❆❆❆❆❆❆❆❆❆套娃❆❆❆❆❆❆❆❆❆
  11. 我是套娃, 我会:
  12. 力大无穷!
  13. 钢筋铁骨!
  14. 会喷水!
  15. 千里眼顺风耳!
  16. 会喷火!

从结果上来看,可套娃是最牛B的!

通过这个例子,慢慢来引申下面的内容。

前提

序列化

修改app01(应用名)目录下的app01_serializers.py,完整代码如下:

  1. from app01 import models
  2. from rest_framework import serializers
  3.  
  4. # 序列化评论的类
  5. class CommentSerializer(serializers.ModelSerializer):
  6. class Meta:
  7. model = models.Comment # Comment表
  8. fields = "__all__" # 序列化所有字段
  9. # 定义额外的参数
  10. extra_kwargs = {
  11. "content": {
  12. "error_messages": {
  13. "required": '内容不能为空',
  14. }
  15. },
  16. "article": {
  17. "error_messages": {
  18. "required": '文章不能为空'
  19. }
  20. }
  21. }
  22.  
  23. # 学校的序列化
  24. class SchoolSerializer(serializers.ModelSerializer):
  25. class Meta:
  26. model = models.School # School表
  27. fields = "__all__"

路由

urls.py代码如下:

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from app01 import app01_urls
  4.  
  5. urlpatterns = [
  6. url(r'^admin/', admin.site.urls),
  7. url(r'api/', include(app01_urls)),
  8. ]

app01_urls.py代码如下:

  1. from django.conf.urls import url
  2. from app01 import views
  3.  
  4. urlpatterns = [
  5. # 学校
  6. url(r'school/$', views.SchoolView.as_view()),
  7. url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
  8. ]

初生牛犊之徒手垒代码阶段

视图

修改views.py,完整代码如下:

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6.  
  7. # Create your views here.
  8.  
  9. class SchoolView(APIView): # 所有记录
  10. def get(self, request, *args, **kwargs): # GET请求
  11. queryset = models.School.objects.all()
  12. # 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
  13. serializers_class = app01_serializers.SchoolSerializer(queryset, many=True)
  14. return Response(serializers_class.data)
  15.  
  16. class SchoolDetail(APIView): # 单条记录
  17. def get(self, request, pk, *args, **kwargs):
  18. queryset = models.School.objects.filter(pk=pk).first()
  19. serializers_class = app01_serializers.SchoolSerializer(queryset)
  20. return Response(serializers_class.data)

浏览器访问url:  http://127.0.0.1:8000/api/school/

效果如下:

访问详情:http://127.0.0.1:8000/api/school/1/

这个时候,需要增加评论表,它也需要上面2个功能:展示所有记录和单条记录

将2个视图函数的代码复制一遍,修改表名和序列化类名

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6.  
  7. # Create your views here.
  8.  
  9. class SchoolView(APIView): # 所有记录
  10. def get(self, request, *args, **kwargs): # GET请求
  11. queryset = models.School.objects.all()
  12. # 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
  13. serializers_class = app01_serializers.SchoolSerializer(queryset, many=True)
  14. return Response(serializers_class.data)
  15.  
  16. class SchoolDetail(APIView): # 单条记录
  17. def get(self, request, pk, *args, **kwargs):
  18. queryset = models.School.objects.filter(pk=pk).first()
  19. serializers_class = app01_serializers.SchoolSerializer(queryset)
  20. return Response(serializers_class.data)
  21.  
  22. class CommentView(APIView): # 所有记录
  23. def get(self, request, *args, **kwargs): # GET请求
  24. queryset = models.Comment.objects.all()
  25. # 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
  26. serializers_class = app01_serializers.CommentSerializer(queryset, many=True)
  27. return Response(serializers_class.data)
  28.  
  29. class CommentDetail(APIView): # 单条记录
  30. def get(self, request, pk, *args, **kwargs):
  31. queryset = models.Comment.objects.filter(pk=pk).first()
  32. serializers_class = app01_serializers.CommentSerializer(queryset)
  33. return Response(serializers_class.data)

修改app01_urls.py,增加2个路径

  1. from django.conf.urls import url
  2. from app01 import views
  3.  
  4. urlpatterns = [
  5. # 学校
  6. url(r'school/$', views.SchoolView.as_view()),
  7. url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
  8. # 评论
  9. url(r'comment/$', views.CommentView.as_view()),
  10. url(r'comment/(?P<pk>\d+)/$', views.CommentDetail.as_view()),
  11. ]

访问所有评论url:  http://127.0.0.1:8000/api/comment/

访问单条评论url:    http://127.0.0.1:8000/api/comment/1/

那么问题来了,再来一个表呢?再复制2个视图函数,修改表名和序列化类名?

这不符合编程习惯,得需要将相同的代码,封装成一个类。那么其他表就可以继承了!

那么接下来的GenericAPIView就展示了它强大的功能

小试牛刀之使用混合类阶段

GenericAPIView

GenericAPIView对APIView再次封装,实现了强大功能:

  • 加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
  • 加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
  • 设置过滤器模板:filter_backends
  • 设置分页模板:pagination_class
  • 加入 lookup_field=”pk”,以及实现了get_object方法: 这个用得场景不多,但十分重要。它们两者的关系同1,要么设置属性,要么重载方法。它们的功能在于获取某一个实例时,指定传进来的后缀是什么。

GenericAPIView的五个扩展类给我们提供了五个方法分别进行增删改查的不同操作,这样我们就不用写那么多函数啦!!

五个扩展类(为啥是5个?答:增删改查,查有两个)

搭配GenericAPIView使用

1.ListModelMixin: 提供list方法快速实现列表视图(多条数据)

2.CreateModelMixin: 提供create方法快速实现创建资源的视图

3.RetrieveModelMixin 提供retrieve方法,可以快速实现返回一个存在的数据对象(需要传入pk)

4.UpdateModelMixin 提供update方法,可以快速实现更新一个存在的数据对象。 提供partial_update方法,可以实现局部更新

5.DestroyModelMixin 提供destroy方法,可以快速实现删除一个存在的数据对象

注意:GenericAPIView不能单独使用,它需要和上面的5个扩展类配合使用才行

源码分析,请参考文章:

https://blog.csdn.net/u013210620/article/details/79869661

ListModelMixin

它返回数据列表,也就是多条数据

使用时,需要导入模块

  1. from rest_framework.mixins import ListModelMixin

RetrieveModelMixin

它负责单条数据的获取、更新、删除

使用时,需要导入模块

  1. from rest_framework.mixins import RetrieveModelMixin

举例:将上面4个视图函数改成GenericAPIView+ListModelMixin+RetrieveModelMixin

使用前,需要导入模块

  1. from rest_framework.generics import GenericAPIView
  2. from rest_framework.mixins import ListModelMixin

GenericAPIView只需要配置queryset和serializer_class 

修改views.py,完整代码如下:

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8.  
  9. # Create your views here.
  10.  
  11. class SchoolView(GenericAPIView, ListModelMixin):
  12. queryset = models.School.objects.all()
  13. serializer_class = app01_serializers.SchoolSerializer
  14.  
  15. def get(self, request, *args, **kwargs): # GET请求
  16. return self.list(request, *args, **kwargs)
  17.  
  18. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  19. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  20. queryset = models.School.objects.all()
  21. serializer_class = app01_serializers.SchoolSerializer
  22.  
  23. def get(self, request, pk, *args, **kwargs): # GET请求
  24. return self.retrieve(request, pk, *args, **kwargs)
  25.  
  26. class CommentView(GenericAPIView, ListModelMixin):
  27. queryset = models.Comment.objects.all()
  28. serializer_class = app01_serializers.CommentSerializer
  29.  
  30. def get(self, request, *args, **kwargs): # GET请求
  31. return self.list(request, *args, **kwargs)
  32.  
  33. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  34. class CommentDetail(GenericAPIView, RetrieveModelMixin):
  35. queryset = models.Comment.objects.all()
  36. serializer_class = app01_serializers.CommentSerializer
  37.  
  38. def get(self, request, pk, *args, **kwargs): # GET请求
  39. return self.retrieve(request, pk, *args, **kwargs)

访问不同的url,效果和上面是一样的!

http://127.0.0.1:8000/api/comment/

http://127.0.0.1:8000/api/comment/1/

http://127.0.0.1:8000/api/school/

http://127.0.0.1:8000/api/school/1/

JsonResponse和Response的区别

JsonResponse和Response都可以返回json对象。不同之处在于:

使用Response时,如果是浏览器访问,就会返回一个页面,效果就是上面的图片。

但是使用postman工具时,返回json数据,并不会有页面。

而JsonResponse则没有这个功能,始终都是json对象

CreateModelMixin

它负责增加一条记录

使用时,需要导入模块

  1. from rest_framework.mixins import CreateModelMixin

举例:增加一条评论

修改views.py,完整代码如下:

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin,CreateModelMixin
  8.  
  9. # Create your views here.
  10.  
  11. class SchoolView(GenericAPIView, ListModelMixin):
  12. queryset = models.School.objects.all()
  13. serializer_class = app01_serializers.SchoolSerializer
  14.  
  15. def get(self, request, *args, **kwargs): # GET请求
  16. return self.list(request, *args, **kwargs)
  17.  
  18. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  19. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  20. queryset = models.School.objects.all()
  21. serializer_class = app01_serializers.SchoolSerializer
  22.  
  23. def get(self, request, pk, *args, **kwargs): # GET请求
  24. return self.retrieve(request, pk, *args, **kwargs)
  25.  
  26. class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
  27. queryset = models.Comment.objects.all()
  28. serializer_class = app01_serializers.CommentSerializer
  29.  
  30. def get(self, request, *args, **kwargs): # GET请求
  31. return self.list(request, *args, **kwargs)
  32.  
  33. def post(self, request, *args, **kwargs): # POST请求
  34. return self.create(request, *args, **kwargs)
  35.  
  36. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  37. class CommentDetail(GenericAPIView, RetrieveModelMixin):
  38. queryset = models.Comment.objects.all()
  39. serializer_class = app01_serializers.CommentSerializer
  40.  
  41. def get(self, request, pk, *args, **kwargs): # GET请求
  42. return self.retrieve(request, pk, *args, **kwargs)

json数据

  1. {
  2. "content": "噗嗤",
  3. "article": 2
  4. }

指定格式为JSON

查看返回结果,它会增加的数据

查看app01_comment表

DestroyModelMixin

删除单条数据

使用时,需要导入模块

  1. from rest_framework.mixins import DestroyModelMixin

举例:删除一条评论,那么在删除之前,可以打印一句话

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8. from rest_framework.mixins import CreateModelMixin, DestroyModelMixin
  9.  
  10. # Create your views here.
  11.  
  12. class SchoolView(GenericAPIView, ListModelMixin):
  13. queryset = models.School.objects.all()
  14. serializer_class = app01_serializers.SchoolSerializer
  15.  
  16. def get(self, request, *args, **kwargs): # GET请求
  17. return self.list(request, *args, **kwargs)
  18.  
  19. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  20. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  21. queryset = models.School.objects.all()
  22. serializer_class = app01_serializers.SchoolSerializer
  23.  
  24. def get(self, request, pk, *args, **kwargs): # GET请求
  25. return self.retrieve(request, pk, *args, **kwargs)
  26.  
  27. class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
  28. queryset = models.Comment.objects.all()
  29. serializer_class = app01_serializers.CommentSerializer
  30.  
  31. def get(self, request, *args, **kwargs): # GET请求
  32. return self.list(request, *args, **kwargs)
  33.  
  34. def post(self, request, *args, **kwargs): # POST请求
  35. return self.create(request, *args, **kwargs)
  36.  
  37. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  38. class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin):
  39. queryset = models.Comment.objects.all()
  40. serializer_class = app01_serializers.CommentSerializer
  41.  
  42. def get(self, request, pk, *args, **kwargs): # GET请求
  43. return self.retrieve(request, pk, *args, **kwargs)
  44.  
  45. def delete(self, request, pk, *args, **kwargs): # DELETE请求
  46. return self.destroy(request, pk, *args, **kwargs)
  47.  
  48. def perform_destroy(self, instance):
  49. print("你真的真的确定要删除了吗?...")
  50. instance.delete()

使用postman发送delete请求,注意:数字后面一定要有 / ,否则不没有效果

因为路由规则定义,必须以 / 结尾!

它的返回结果为空

查看Pycharm控制台输出:

你真的真的确定要删除了吗?...

UpdateModelMixin

更新单条数据

使用时,需要导入模块

  1. from rest_framework.mixins import UpdateModelMixin

举例:更新一条评论

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8. from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
  9.  
  10. # Create your views here.
  11.  
  12. class SchoolView(GenericAPIView, ListModelMixin):
  13. queryset = models.School.objects.all()
  14. serializer_class = app01_serializers.SchoolSerializer
  15.  
  16. def get(self, request, *args, **kwargs): # GET请求
  17. return self.list(request, *args, **kwargs)
  18.  
  19. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  20. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  21. queryset = models.School.objects.all()
  22. serializer_class = app01_serializers.SchoolSerializer
  23.  
  24. def get(self, request, pk, *args, **kwargs): # GET请求
  25. return self.retrieve(request, pk, *args, **kwargs)
  26.  
  27. class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
  28. queryset = models.Comment.objects.all()
  29. serializer_class = app01_serializers.CommentSerializer
  30.  
  31. def get(self, request, *args, **kwargs): # GET请求
  32. return self.list(request, *args, **kwargs)
  33.  
  34. def post(self, request, *args, **kwargs): # POST请求
  35. return self.create(request, *args, **kwargs)
  36.  
  37. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  38. class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
  39. queryset = models.Comment.objects.all()
  40. serializer_class = app01_serializers.CommentSerializer
  41.  
  42. def get(self, request, pk, *args, **kwargs): # GET请求
  43. return self.retrieve(request, pk, *args, **kwargs)
  44.  
  45. def delete(self, request, pk, *args, **kwargs): # DELETE请求
  46. return self.destroy(request, pk, *args, **kwargs)
  47.  
  48. def perform_destroy(self, instance):
  49. print("你真的真的确定要删除了吗?...")
  50. instance.delete()
  51.  
  52. def put(self, request, pk, *args, **kwargs): # PUT请求
  53. return self.update(request, pk, *args, **kwargs)

json数据

  1. {
  2. "id": 6,
  3. "content": "从前的日色变得慢",
  4. "article": 1
  5. }

使用put发送,选择JSON

如果返回结果是:

415(Unsupported Media Type)不支持的类型异常

请查看Headers,一定要勾选

再次发送,查看返回结果

查看表app01_comment,发现记录更新了!

牛气冲天之使用通用类

Django REST framework提供了9个通用视图,详情请参考以下链接中的《混凝土视图类》

https://www.cnblogs.com/yangxiaoling/p/6914880.html

RetrieveUpdateDestroyAPIView

用于读写删除端点来表示单个模型实例

提供getputpatchdelete方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestroyModelMixin

它相当于上面葫芦娃例子中的奇数娃

使用需要导入模块

  1. from rest_framework.generics import RetrieveUpdateDestroyAPIView

举例:将CommentDetail改造成RetrieveUpdateDestroyAPIView

它拥有get,put,patch和delete方法处理,所以之前的那些方法,都可以干掉了!

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8. from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
  9.  
  10. # Create your views here.
  11.  
  12. class SchoolView(GenericAPIView, ListModelMixin):
  13. queryset = models.School.objects.all()
  14. serializer_class = app01_serializers.SchoolSerializer
  15.  
  16. def get(self, request, *args, **kwargs): # GET请求
  17. return self.list(request, *args, **kwargs)
  18.  
  19. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  20. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  21. queryset = models.School.objects.all()
  22. serializer_class = app01_serializers.SchoolSerializer
  23.  
  24. def get(self, request, pk, *args, **kwargs): # GET请求
  25. return self.retrieve(request, pk, *args, **kwargs)
  26.  
  27. class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
  28. queryset = models.Comment.objects.all()
  29. serializer_class = app01_serializers.CommentSerializer
  30.  
  31. def get(self, request, *args, **kwargs): # GET请求
  32. return self.list(request, *args, **kwargs)
  33.  
  34. def post(self, request, *args, **kwargs): # POST请求
  35. return self.create(request, *args, **kwargs)
  36.  
  37. class CommentDetail(RetrieveUpdateDestroyAPIView):
  38. queryset = models.Comment.objects.all()
  39. serializer_class = app01_serializers.CommentSerializer

测试GET

测试PUT

查看返回结果

查看表app01_comment

测试DELETE

它的返回结果是空的

查看表记录,发现少了一条记录

注意:它没有POST,否则会返回"detail": "Method \"POST\" not allowed."

ListCreateAPIView

用于读写端点来表示模型实例的集合

提供getpost方法处理程序。

扩展:GenericAPIViewListModelMixinCreateModelMixin

它相当于上面葫芦娃例子中的偶数娃

使用需要导入模块

  1. from rest_framework.generics import ListCreateAPIView

举例:将CommentView改造成ListCreateAPIView

它拥有get,post方法处理,所以之前的那些方法,都可以干掉了!

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8. from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
  9.  
  10. # Create your views here.
  11.  
  12. class SchoolView(GenericAPIView, ListModelMixin):
  13. queryset = models.School.objects.all()
  14. serializer_class = app01_serializers.SchoolSerializer
  15.  
  16. def get(self, request, *args, **kwargs): # GET请求
  17. return self.list(request, *args, **kwargs)
  18.  
  19. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  20. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  21. queryset = models.School.objects.all()
  22. serializer_class = app01_serializers.SchoolSerializer
  23.  
  24. def get(self, request, pk, *args, **kwargs): # GET请求
  25. return self.retrieve(request, pk, *args, **kwargs)
  26.  
  27. class CommentView(ListCreateAPIView):
  28. queryset = models.Comment.objects.all()
  29. serializer_class = app01_serializers.CommentSerializer
  30.  
  31. class CommentDetail(RetrieveUpdateDestroyAPIView):
  32. queryset = models.Comment.objects.all()
  33. serializer_class = app01_serializers.CommentSerializer

测试GET

测试POST,注意后面没有数字

查看返回结果

查看表app01_comment,发现多了一条记录

牛牛牛牛之使用视图集

ModelViewSet

ModelViewSet视图集会自动提供list,create, retrieve, update & destroy这些行为,

查看源代码:它有6个功能

也就说它具有5个葫芦娃的能力,也就是上面面向对象讲到的套娃

使用时,需要导入模块

  1. from rest_framework.viewsets import ModelViewSet

处理器方法只有在定义了URLConf的时候才会绑定这些行为
在urls.py文件中,我们把ViewSet绑定到一些具体的视图上

修改app01_urls.py

  1. from django.conf.urls import url
  2. from app01 import views
  3.  
  4. urlpatterns = [
  5. # 学校
  6. url(r'school/$', views.SchoolView.as_view()),
  7. url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
  8.  
  9. # 评论
  10. url(r'comment/$', views.CommentViewSet.as_view({
  11. 'get': "list",
  12. 'post': 'create'
  13. })),
  14.  
  15. url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({
  16. 'get': 'retrieve',
  17. 'put': 'update',
  18. 'delete': 'destroy'
  19. })),
  20. ]

参数解释:

get,post,put,delete分别表示不同的请求方式

后面对应的值分别是ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

修改views.py,增加一个视图函数,注释多余的代码

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from rest_framework.views import APIView
  4. from app01 import app01_serializers # 导入自定义的序列化
  5. from rest_framework.response import Response
  6. from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
  7. from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
  8. from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
  9. from rest_framework.viewsets import ModelViewSet
  10.  
  11. # Create your views here.
  12.  
  13. class SchoolView(GenericAPIView, ListModelMixin):
  14. queryset = models.School.objects.all()
  15. serializer_class = app01_serializers.SchoolSerializer
  16.  
  17. def get(self, request, *args, **kwargs): # GET请求
  18. return self.list(request, *args, **kwargs)
  19.  
  20. # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
  21. class SchoolDetail(GenericAPIView, RetrieveModelMixin):
  22. queryset = models.School.objects.all()
  23. serializer_class = app01_serializers.SchoolSerializer
  24.  
  25. def get(self, request, pk, *args, **kwargs): # GET请求
  26. return self.retrieve(request, pk, *args, **kwargs)
  27.  
  28. # class CommentView(ListCreateAPIView):
  29. # queryset = models.Comment.objects.all()
  30. # serializer_class = app01_serializers.CommentSerializer
  31. #
  32. #
  33. # class CommentDetail(RetrieveUpdateDestroyAPIView):
  34. # queryset = models.Comment.objects.all()
  35. # serializer_class = app01_serializers.CommentSerializer
  36.  
  37. class CommentViewSet(ModelViewSet):
  38. queryset = models.Comment.objects.all()
  39. serializer_class = app01_serializers.CommentSerializer

一个视图函数,就搞定了5种请求方式,惊叹不已!

测试GET

后面的几种请求方式,大家可以自行测试!

再来一牛之高级路由

视图

同上,还是使用ModelViewSet

路由

因为我们正在使用ViewSet代替View,实际上已经不再需要自己来设计URL的配置了。将资源和视图、URL绑定到一起是一个可以自动完成的过程,只需要使用Router即可。我们需要做的就是将视图集注册到Router上去而已。

修改app01_urls.py

  1. from django.conf.urls import url
  2. from app01 import views
  3.  
  4. urlpatterns = [
  5. # 学校
  6. url(r'school/$', views.SchoolView.as_view()),
  7. url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
  8.  
  9. # 评论
  10. # url(r'comment/$', views.CommentViewSet.as_view({
  11. # 'get': "list",
  12. # 'post': 'create'
  13. # })),
  14. #
  15. # url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({
  16. # 'get': 'retrieve',
  17. # 'put': 'update',
  18. # 'delete': 'destroy'
  19. # })),
  20. ]
  21.  
  22. from rest_framework.routers import DefaultRouter
  23.  
  24. router = DefaultRouter()
  25. # 注册路由,表示路径comment对应视图函数CommentViewSet
  26. router.register(r'comment', views.CommentViewSet)
  27. urlpatterns += router.urls

将ViewSets注册到Routers的过程实际上类似于提供一个urlpattern。我们引入了两个参数,一个是views的URL prefix,另一个是viewset本身。 
我们使用的DefaultRouter也会自动地帮我们创建API root视图,多余路由可以注释掉了!

赠图一张,祝君好运

二、django logging配置

做开发开不开日志,以下是我在工作中写Django项目常用的logging配置。

配置

修改settings.py,最后一行添加

  1. BASE_LOG_DIR = os.path.join(BASE_DIR, 'log')
  2. # 日志相关配置
  3. LOGGING = {
  4. 'version': 1, # 保留字段
  5. 'disable_existing_loggers': False, # 不要禁用已经存在的logger实例
  6.  
  7. 'formatters': { # 定义三种日志显示的格式
  8. 'standard': {
  9. 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
  10. '[%(levelname)s][%(message)s]'
  11. },
  12. 'simple': {
  13. 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
  14. },
  15. 'collect': {
  16. 'format': '%(message)s'
  17. }
  18. },
  19.  
  20. 'filters': { # 定义一个过滤规则
  21. 'require_debug_true': {
  22. '()': 'django.utils.log.RequireDebugTrue',
  23. },
  24. },
  25.  
  26. 'handlers': { # 日志流的处理方式
  27. 'console': { # 把日志打印到终端
  28. 'level': 'DEBUG',
  29. 'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
  30. 'class': 'logging.StreamHandler',
  31. 'formatter': 'simple'
  32. },
  33. 'default': {
  34. 'level': 'INFO',
  35. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  36. 'filename': os.path.join(BASE_LOG_DIR, "info.log"), # 日志文件
  37. 'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
  38. 'backupCount': 3, #
  39. 'formatter': 'standard',
  40. 'encoding': 'utf-8',
  41. },
  42. 'error': {
  43. 'level': 'ERROR',
  44. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  45. 'filename': os.path.join(BASE_LOG_DIR, "err.log"), # 日志文件
  46. 'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
  47. 'backupCount': 5,
  48. 'formatter': 'standard',
  49. 'encoding': 'utf-8',
  50. },
  51. 'collect': {
  52. 'level': 'INFO',
  53. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  54. 'filename': os.path.join(BASE_LOG_DIR, "collect.log"),
  55. 'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
  56. 'backupCount': 5,
  57. 'formatter': 'collect',
  58. 'encoding': "utf-8"
  59. }
  60. },
  61. 'loggers': {
  62.  
  63. # 默认的logger应用如下配置
  64. '': {
  65. 'handlers': ['default', 'console', 'error'], # 上线之后可以把'console'移除
  66. 'level': 'DEBUG',
  67. 'propagate': True, # 是否向父级logger实例传递日志信息
  68. },
  69.  
  70. # 名为 'collect'的logger还单独处理
  71. 'collect': {
  72. 'handlers': ['console', 'collect'],
  73. 'level': 'INFO',
  74. }
  75. },
  76. }

注意要手动创建log目录,目录里面创建3个文件err.log,info.log,collect.log

使用

在视图函数中使用时,先导入模块,并声明变量

  1. import logging
  2. # 生成一个以当前文件名为名字的 logger实例
  3. logger = logging.getLogger(__name__)
  4. # 生成一个名字为collect的日志实例
  5. collect_logger = logging.getLogger('collect')

然后在逻辑代码中加入

  1. logger.warning('找不到记录...')
  2. 或者
  3. collect_logger.info(name)

Python logger流示图

附:Python logger流示图

三、django-debug-toolbar使用指南

介绍

django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面板内容的更多详细信息。

github地址

文档地址

安装

  1. pip3 install django-debug-toolbar

配置

1. settings.py中

将 debug_toolbar 添加到 INSTALL_APPS 中,最后一行添加

  1. INSTALLED_APPS = [

  2. 'debug_toolbar',
  3. ]

2. urls.py中

  1. from django.conf import settings
  2. from django.conf.urls import include, url
  3.  
  4. if settings.DEBUG:
  5. import debug_toolbar
  6. urlpatterns = [
  7. url(r'^__debug__/', include(debug_toolbar.urls)),
  8. ] + urlpatterns

3. settings.py中

在中间件中加入DebugToolbarMiddleware,最后一行添加

  1. MIDDLEWARE = [
  2. # ...
  3. 'debug_toolbar.middleware.DebugToolbarMiddleware',
  4. ]

4.加入 INTERNAL_IPS

如果是本机调试,还在将127.0.0.1加入 INTERNAL_IPS

在settings.py中加入以下配置项:

  1. INTERNAL_IPS = ['127.0.0.1', ]

5.  配置jQuery的URL

django-debug-toolbar 默认使用的是Google的地址,默认配置如下:

  1. JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'

国内用不了的话可以在settings.py中配置一下,例如(我这里特意选用了和原作者相同版本的jQuery):

修改settings.py,最后一行添加

  1. DEBUG_TOOLBAR_CONFIG = {
  2. "JQUERY_URL": '//cdn.bootcss.com/jquery/2.2.4/jquery.min.js',
  3. }

或者你如果在Django项目中使用了jquery的话就可以直接将这一项置为空,那么django-debug-toolbar 就会使用你项目中用到的jquery:

  1. DEBUG_TOOLBAR_CONFIG = {
  2. "JQUERY_URL": '',
  3. }

使用

访问具体路径的时候在页面右侧有各项配置面板,点击即可查看各种调试信息。

python 全栈开发,Day96(Django REST framework 视图,django logging配置,django-debug-toolbar使用指南)的更多相关文章

  1. python 全栈开发,Day111(客户管理之 编辑权限(二),Django表单集合Formset,ORM之limit_choices_to,构造家族结构)

    昨日内容回顾 1. 权限系统的流程? 2. 权限的表有几个? 3. 技术点 中间件 session orm - 去重 - 去空 inclusion_tag filter 有序字典 settings配置 ...

  2. python 全栈开发,Day72(昨日作业讲解,昨日内容回顾,Django多表创建)

    昨日作业讲解 1.图书管理系统 实现功能:book单表的增删改查 1.1 新建一个项目bms,创建应用book.过程略... 1.2 手动创建static目录,并在目录里面创建css文件夹,修改set ...

  3. python 全栈开发,Day26(hashlib文件一致性,configparser,logging,collections模块,deque,OrderedDict)

    一.hashlib文件一致性校验 为何要进行文件一致性校验? 为了确保你得到的文件是正确的版本,而没有被注入病毒和木马程序.例如我们经常在网上下载软件,而这些软件已经被注入了一些广告和病毒等,如果不进 ...

  4. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  5. python全栈开发目录

    python全栈开发目录 Linux系列 python基础 前端~HTML~CSS~JavaScript~JQuery~Vue web框架们~Django~Flask~Tornado 数据库们~MyS ...

  6. Python全栈开发相关课程

    Python全栈开发 Python入门 Python安装 Pycharm安装.激活.使用 Python基础 Python语法 Python数据类型 Python进阶 面向对象 网络编程 并发编程 数据 ...

  7. Python 全栈开发【第0篇】:目录

    Python 全栈开发[第0篇]:目录   第一阶段:Python 开发入门 Python 全栈开发[第一篇]:计算机原理&Linux系统入门 Python 全栈开发[第二篇]:Python基 ...

  8. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  9. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  10. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

随机推荐

  1. Linux下环境变量设置技巧

    Linux下环境变量设置技巧,不用/etc/profile而是在/etc/profile.d目录下新建特定的shell文件来设置 区别: 1.两个文件都是设置环境变量文件的,/etc/profile是 ...

  2. Django 2.0.1 官方文档翻译:编写你的第一个djang补丁(page 15)

    编写你的第一个djang补丁(page 15) 介绍 有兴趣为社区做一些贡献?可能你发现了django中的一个你想修复的bug,或者你你想添加一个小小的功能. 回馈django就是解决你遇到的问题的最 ...

  3. vue自学入门-1(Windows下搭建vue环境)

    本人是一个喜欢动手的程序员,先跑起来个HelloWorld,增加感性认识,这三篇入门文章,花了不到一个小时,从网上找资料,程序跑通后,整理出来的,有的新人可能去哪找资料,运行代码都不知道,分享出来,大 ...

  4. 三、u-boot 的配置-mkconfig 脚本

    3.1 mkconfig 脚本 100ask24x0_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL ...

  5. Win10 x64 + CUDA 10.0 + cuDNN v7.5 + TensorFlow GPU 1.13 安装指南

    Win10 x64 + CUDA 10.0 + cuDNN v7.5 + TensorFlow GPU 1.13 安装指南 Update : 2019.03.08 0. 环境说明 硬件:Ryzen R ...

  6. hadoop - 基础操作

    查看文件: [root@hadoop hadoop]# hadoop fs -lsr /drwxr-xr-x - root supergroup 0 2016-12-27 10:49 /homedrw ...

  7. JavaScript之调试工具之断言assert

    1.单点断言 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...

  8. UE4联机编译光照

    UE4联机编译光照需要SwarmCoordinator以及SwarmAgent,在Engine\Binaries\DotNET目录下. SwarmAgent 我们主要关注Distribution Se ...

  9. c#将前端传来的Json解析成对象

    描述:因工作中需要将C#中的Json字符串转换为对象,对此记录下. 解决办法: 1.前端传过来的Json字符串,OrderAppModuleJson即前端传递到后端的Json字符串 string st ...

  10. php 全局变量问题

    当在函数里通过require_once包含另外php文件. 而另外php文件包含了另外php文件,而该php文件的函数需要另外的php文件. 例子: installment_maintenance_s ...