昨日内容回顾

1. Serializer(序列化)
1. ORM对应的query_set和ORM对象转换成JSON格式的数据
1. 在序列化类中定义自定义的字段:SerializerMethodField
在类中定义 get_自定义字段名(self, obj)方法
2. read_only 只在显示(查询)时才会有效。 2. 对前端POST过来的数据做有效性的校验
1. 一定要将数据以data=的形式传递到序列化类中!!!
ser_obj = CommentSerializer(data=comment_data)
2. 判断数据是否有效
ser_obj.is_valid(): 欠一个源码
ser_obj.validated_data 中保存经过校验的有效数据 3. 局部钩子
定义一个validate_字段名(self, value)
4. 全局钩子
定义一个validate方法 3. .save()方法将符合要求的数据存入数据库
1. 本质上还是调用ORM的create()方法
类名.objects.create(**ser_obj.validated_data) 2. 超链接的序列化
1. 超连接字段的三个参数
# 文章超链接序列化
class ArticleHyperLinkedSerializer(serializers.HyperlinkedModelSerializer):
# view_name参数 默认使用 表名-detail
# lookup_url_kwarg参数 默认使用pk,指的是反向生成URL的时候 路由中的分组命名匹配的key
# lookup_field参数 默认使用的pk, 指的是反向生成URL的时候, 路由中分组命名匹配的value
school = serializers.HyperlinkedIdentityField(
view_name='school-detail111',
lookup_url_kwarg='name',
lookup_field='school_name'
)
2. 想要生成完整的超链接API,在序列化的时候还要传入 context={'request': request}
ser_obj = app01_serializers.ArticleHyperLinkedSerializer(all_article, many=True, context={'request': request})
1. 想要生成相对路径
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个呢?到最后,你就知道了!

class Wa1(object):
name = "红娃" def f1(self):
print("力大无穷!") class Wa2(object):
name = '橙娃' def f2(self):
print('千里眼顺风耳!') class Wa3(object):
name = '黄娃' def f3(self):
print('钢筋铁骨!') class Wa4(object):
name = '绿娃' def f4(self):
print("会喷火!") class Wa5(object):
name = '青蛙' def f5(self):
print("会喷水!")

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

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

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

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

完整代码如下:

class Wa1(object):
name = "红娃" def f1(self):
print("力大无穷!") class Wa2(object):
name = '橙娃' def f2(self):
print('千里眼顺风耳!') class Wa3(object):
name = '黄娃' def f3(self):
print('钢筋铁骨!') class Wa4(object):
name = '绿娃' def f4(self):
print("会喷火!") class Wa5(object):
name = '青蛙' def f5(self):
print("会喷水!") class Jishuwa(Wa1, Wa3, Wa5):
name = '奇数娃' def info(self):
print("我是%s,我会:" %self.name)
self.skill() def skill(self): # 技能
self.f1()
self.f3()
self.f5() class Oushuwa(Wa2, Wa4):
name = '偶数娃' def info(self):
print("我是%s,我会:" % self.name)
self.skill() def skill(self): # 技能
self.f2()
self.f4() class Taowa(Jishuwa, Oushuwa):
name = '套娃' def info(self):
print("我是{}, 我会:".format(self.name))
self.skill() def skill(self): # 技能
Jishuwa.skill(self)
Oushuwa.skill(self) print('奇数娃'.center(20, '❆'))
role1 = Jishuwa()
role1.info() print('偶数娃'.center(20, '❆'))
role2 = Oushuwa()
role2.info() print('套娃'.center(20, '❆'))
role3 = Taowa()
role3.info()

执行输出:

❆❆❆❆❆❆❆❆奇数娃❆❆❆❆❆❆❆❆❆
我是奇数娃,我会:
力大无穷!
钢筋铁骨!
会喷水!
❆❆❆❆❆❆❆❆偶数娃❆❆❆❆❆❆❆❆❆
我是偶数娃,我会:
千里眼顺风耳!
会喷火!
❆❆❆❆❆❆❆❆❆套娃❆❆❆❆❆❆❆❆❆
我是套娃, 我会:
力大无穷!
钢筋铁骨!
会喷水!
千里眼顺风耳!
会喷火!

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

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

前提

序列化

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

from app01 import models
from rest_framework import serializers # 序列化评论的类
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = models.Comment # Comment表
fields = "__all__" # 序列化所有字段
# 定义额外的参数
extra_kwargs = {
"content": {
"error_messages": {
"required": '内容不能为空',
}
},
"article": {
"error_messages": {
"required": '文章不能为空'
}
}
} # 学校的序列化
class SchoolSerializer(serializers.ModelSerializer):
class Meta:
model = models.School # School表
fields = "__all__"

路由

urls.py代码如下:

from django.conf.urls import url,include
from django.contrib import admin
from app01 import app01_urls urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'api/', include(app01_urls)),
]

app01_urls.py代码如下:

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

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

视图

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response # Create your views here. class SchoolView(APIView): # 所有记录
def get(self, request, *args, **kwargs): # GET请求
queryset = models.School.objects.all()
# 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
serializers_class = app01_serializers.SchoolSerializer(queryset, many=True)
return Response(serializers_class.data) class SchoolDetail(APIView): # 单条记录
def get(self, request, pk, *args, **kwargs):
queryset = models.School.objects.filter(pk=pk).first()
serializers_class = app01_serializers.SchoolSerializer(queryset)
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个视图函数的代码复制一遍,修改表名和序列化类名

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response # Create your views here. class SchoolView(APIView): # 所有记录
def get(self, request, *args, **kwargs): # GET请求
queryset = models.School.objects.all()
# 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
serializers_class = app01_serializers.SchoolSerializer(queryset, many=True)
return Response(serializers_class.data) class SchoolDetail(APIView): # 单条记录
def get(self, request, pk, *args, **kwargs):
queryset = models.School.objects.filter(pk=pk).first()
serializers_class = app01_serializers.SchoolSerializer(queryset)
return Response(serializers_class.data) class CommentView(APIView): # 所有记录
def get(self, request, *args, **kwargs): # GET请求
queryset = models.Comment.objects.all()
# 使用自定义序列化类。当返回结果不止一条时,要指定many=True参数
serializers_class = app01_serializers.CommentSerializer(queryset, many=True)
return Response(serializers_class.data) class CommentDetail(APIView): # 单条记录
def get(self, request, pk, *args, **kwargs):
queryset = models.Comment.objects.filter(pk=pk).first()
serializers_class = app01_serializers.CommentSerializer(queryset)
return Response(serializers_class.data)

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

from django.conf.urls import url
from app01 import views urlpatterns = [
# 学校
url(r'school/$', views.SchoolView.as_view()),
url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
# 评论
url(r'comment/$', views.CommentView.as_view()),
url(r'comment/(?P<pk>\d+)/$', views.CommentDetail.as_view()),
]

访问所有评论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

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

使用时,需要导入模块

from rest_framework.mixins import ListModelMixin

RetrieveModelMixin

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

使用时,需要导入模块

from rest_framework.mixins import RetrieveModelMixin

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

使用前,需要导入模块

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

GenericAPIView只需要配置queryset和serializer_class 

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class CommentDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, pk, *args, **kwargs): # GET请求
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

它负责增加一条记录

使用时,需要导入模块

from rest_framework.mixins import CreateModelMixin

举例:增加一条评论

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin,CreateModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # POST请求
return self.create(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class CommentDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs)

json数据

{
"content": "噗嗤",
"article": 2
}

指定格式为JSON

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

查看app01_comment表

DestroyModelMixin

删除单条数据

使用时,需要导入模块

from rest_framework.mixins import DestroyModelMixin

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # POST请求
return self.create(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) def delete(self, request, pk, *args, **kwargs): # DELETE请求
return self.destroy(request, pk, *args, **kwargs) def perform_destroy(self, instance):
print("你真的真的确定要删除了吗?...")
instance.delete()

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

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

它的返回结果为空

查看Pycharm控制台输出:

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

UpdateModelMixin

更新单条数据

使用时,需要导入模块

from rest_framework.mixins import UpdateModelMixin

举例:更新一条评论

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # POST请求
return self.create(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) def delete(self, request, pk, *args, **kwargs): # DELETE请求
return self.destroy(request, pk, *args, **kwargs) def perform_destroy(self, instance):
print("你真的真的确定要删除了吗?...")
instance.delete() def put(self, request, pk, *args, **kwargs): # PUT请求
return self.update(request, pk, *args, **kwargs)

json数据

{
"id": 6,
"content": "从前的日色变得慢",
"article": 1
}

使用put发送,选择JSON

如果返回结果是:

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

请查看Headers,一定要勾选

再次发送,查看返回结果

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

牛气冲天之使用通用类

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

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

RetrieveUpdateDestroyAPIView

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

提供getputpatchdelete方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestroyModelMixin

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

使用需要导入模块

from rest_framework.generics import RetrieveUpdateDestroyAPIView

举例:将CommentDetail改造成RetrieveUpdateDestroyAPIView

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # POST请求
return self.create(request, *args, **kwargs) class CommentDetail(RetrieveUpdateDestroyAPIView):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer

测试GET

测试PUT

查看返回结果

查看表app01_comment

测试DELETE

它的返回结果是空的

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

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

ListCreateAPIView

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

提供getpost方法处理程序。

扩展:GenericAPIViewListModelMixinCreateModelMixin

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

使用需要导入模块

from rest_framework.generics import ListCreateAPIView

举例:将CommentView改造成ListCreateAPIView

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) class CommentView(ListCreateAPIView):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer class CommentDetail(RetrieveUpdateDestroyAPIView):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer

测试GET

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

查看返回结果

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

牛牛牛牛之使用视图集

ModelViewSet

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

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

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

使用时,需要导入模块

from rest_framework.viewsets import ModelViewSet

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

修改app01_urls.py

from django.conf.urls import url
from app01 import views urlpatterns = [
# 学校
url(r'school/$', views.SchoolView.as_view()),
url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), # 评论
url(r'comment/$', views.CommentViewSet.as_view({
'get': "list",
'post': 'create'
})), url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'delete': 'destroy'
})),
]

参数解释:

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

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

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

from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
from rest_framework.viewsets import ModelViewSet # Create your views here. class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET请求
return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET请求
return self.retrieve(request, pk, *args, **kwargs) # class CommentView(ListCreateAPIView):
# queryset = models.Comment.objects.all()
# serializer_class = app01_serializers.CommentSerializer
#
#
# class CommentDetail(RetrieveUpdateDestroyAPIView):
# queryset = models.Comment.objects.all()
# serializer_class = app01_serializers.CommentSerializer class CommentViewSet(ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer

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

测试GET

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

再来一牛之高级路由

视图

同上,还是使用ModelViewSet

路由

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

修改app01_urls.py

from django.conf.urls import url
from app01 import views urlpatterns = [
# 学校
url(r'school/$', views.SchoolView.as_view()),
url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), # 评论
# url(r'comment/$', views.CommentViewSet.as_view({
# 'get': "list",
# 'post': 'create'
# })),
#
# url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({
# 'get': 'retrieve',
# 'put': 'update',
# 'delete': 'destroy'
# })),
] from rest_framework.routers import DefaultRouter router = DefaultRouter()
# 注册路由,表示路径comment对应视图函数CommentViewSet
router.register(r'comment', views.CommentViewSet)
urlpatterns += router.urls

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

赠图一张,祝君好运

二、django logging配置

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

配置

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

BASE_LOG_DIR = os.path.join(BASE_DIR, 'log')
# 日志相关配置
LOGGING = {
'version': 1, # 保留字段
'disable_existing_loggers': False, # 不要禁用已经存在的logger实例 'formatters': { # 定义三种日志显示的格式
'standard': {
'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
'[%(levelname)s][%(message)s]'
},
'simple': {
'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
},
'collect': {
'format': '%(message)s'
}
}, 'filters': { # 定义一个过滤规则
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
}, 'handlers': { # 日志流的处理方式
'console': { # 把日志打印到终端
'level': 'DEBUG',
'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "info.log"), # 日志文件
'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
'backupCount': 3, #
'formatter': 'standard',
'encoding': 'utf-8',
},
'error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "err.log"), # 日志文件
'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
'backupCount': 5,
'formatter': 'standard',
'encoding': 'utf-8',
},
'collect': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "collect.log"),
'maxBytes': 1024 * 1024 * 500, # 日志大小 500M
'backupCount': 5,
'formatter': 'collect',
'encoding': "utf-8"
}
},
'loggers': { # 默认的logger应用如下配置
'': {
'handlers': ['default', 'console', 'error'], # 上线之后可以把'console'移除
'level': 'DEBUG',
'propagate': True, # 是否向父级logger实例传递日志信息
}, # 名为 'collect'的logger还单独处理
'collect': {
'handlers': ['console', 'collect'],
'level': 'INFO',
}
},
}

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

使用

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

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

然后在逻辑代码中加入

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

Python logger流示图

附:Python logger流示图

三、django-debug-toolbar使用指南

介绍

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

github地址

文档地址

安装

pip3 install django-debug-toolbar

配置

1. settings.py中

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

INSTALLED_APPS = [

'debug_toolbar',
]

2. urls.py中

from django.conf import settings
from django.conf.urls import include, url if settings.DEBUG:
import debug_toolbar
urlpatterns = [
url(r'^__debug__/', include(debug_toolbar.urls)),
] + urlpatterns

3. settings.py中

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

MIDDLEWARE = [
# ...
'debug_toolbar.middleware.DebugToolbarMiddleware',
]

4.加入 INTERNAL_IPS

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

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

INTERNAL_IPS = ['127.0.0.1', ]

5.  配置jQuery的URL

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

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

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

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

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

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

DEBUG_TOOLBAR_CONFIG = {
"JQUERY_URL": '',
}

使用

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

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的一个find命令配合rm删除某天前的文件

    语句写法: find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \; 例1: 将/usr/local/backups目录下所有10天前 ...

  2. Cloud9 开发环境部署

    安装和部署 cloud9 云端开发环境 简介 Cloud9 是亚马逊发布的一款基于云端的开发环境. AWS Cloud9 是一种基于云的集成开发环境 (IDE),您只需要一个浏览器,即可编写.运行和调 ...

  3. cdqz2017-test11-占卜的准备

    #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #defi ...

  4. bzoj千题计划298:bzoj3997: [TJOI2015]组合数学

    http://www.lydsy.com/JudgeOnline/problem.php?id=3997 最小链覆盖=最长反链长度 所以题目等价于寻找一条从右上角到左下角的最长路 #include&l ...

  5. bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿

    http://www.lydsy.com/JudgeOnline/problem.php?id=3629 约数和定理: 若n的标准分解式为 p1^k1 * p2^k2 …… 那么n的约数和= π (Σ ...

  6. Keil4 几例异常解决办法

    以下几个问题在Keil5上没有发现,不过因为下载的例子都是Keil4,强迫症让我用起了Keil4 错误一:main.c: Warning: C3910W: Old syntax, please use ...

  7. 10 SpringBoot全面接管SpringMVC

    Spring Boot官方文档描述 If you want to keep Spring Boot MVC features and you want to add additional MVC co ...

  8. Linux 4.10.8 根文件系统制作(一)---环境搭建

    一.工具 制作工具为busybox 下载地址:https://busybox.net/ 解压: 二.制作文件系统 进入目录,执行make menuconfig: 2.1 busybox setting ...

  9. ettercap 模块使用

    Ettercap的过滤规则只能经过编译之后才能由-F参数载入到ettercap中使用. 编译过滤规则命令是:etterfilter filter.ecf -o filter.ef. 过滤规则的语法与C ...

  10. Nginx 虚拟主机示例

    Nginx server 模块 server { // 标识虚拟主机开始 listen ; ## // 指定虚拟主机服务器端口 server_name localhost; // 指定 IP地址或者域 ...