目录
1.drf简单使用
2.drf快速使用
3.CBV源码分析和APIView源码分析
4.Request对象分析
5.序列化器介绍和使用
1.drf简单使用
1 可以更方便的使用django写出符合resful规范的接口(不用也可以写符合规范的接口)
2 是一个app
3 pip3 install djangorestframework
4 https://www.django-rest-framework.org/
5 简单使用(csrf已经禁用掉了)
#路由
path('test/', views.Test.as_view()),
# 视图类
from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
def get(self,request):
return Response({'name':'lqz','age':'19'})
def post(self,request):
return Response({'name': 'egon', 'age': '19'})
# 注册app
INSTALLED_APPS = [
'rest_framework'
]
# 在请求地址中访问
http://127.0.0.1:8001/test/
2.drf快速使用
2.1 views.py
from rest_framework.viewsets import ModelViewSet
from app import models
from app.serializer import BookSerializer
class BookView(ModelViewSet):
serializer_class =BookSerializer
queryset = models.Book.objects.all()
2.2 serializer.py
from rest_framework.serializers import ModelSerializer
from app import models
class BookSerializer(ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
2.3 urls.py
from rest_framework.routers import SimpleRouter
from app import views
router = SimpleRouter()
router.register('books', views.BookView)
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls
2.4 在setting的app中配置
INSTALLED_APPS = [
'rest_framework'
]
2.5 models.py
class Book(models.Model):
name = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
price = models.IntegerField()
3.CBV源码分析和APIView源码分析
path('test/',views.TestView.as_view()),
# path('test/',View类的as_view内部有个view闭包函数内存地址),
'''
1 path的第二个参数是:View类的as_view内部有个view闭包函数内存地址
2 一旦有请求来了,匹配test路径成功
3 执行第二个参数view函数内存地址(requset)
4 本质执行了self.dispatch(request)
5 通过反射去获得方法(如果是get请求,就是get方法)
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
6 执行get方法,传入参数
handler(request, *args, **kwargs)
'''
APIView的执行流程
# path('test/',APIView类的as_view内部是用了View的as_view内的view闭包函数),
'''
1 path的第二个参数是:APIView类的as_view内部是用了View的as_view内的view闭包函数
2 一旦有请求来了,匹配test路径成功
3 执行第二个参数view函数内存地址(requset),还是执行View的as_view内的view闭包函数,但是加了个csrf_exempt装饰器
4 所以,继承了APIView的所有接口,都没有csrf的校验了 (*****************)
5 执行self.dispatch(request)----》APIView类的
def dispatch(self, request, *args, **kwargs):
# 以后所有的request对象,都是****新的request对象***,它是drf的Request类的对象
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
#整个drf的执行流程内的权限,频率,认证
self.initial(request, *args, **kwargs)
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
# 全局异常
response = self.handle_exception(exc)
# 响应
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
'''
### request = self.initialize_request(request, *args, **kwargs)
##返回的request对象是drf Request类的request对象
def initialize_request(self, request, *args, **kwargs):
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
### *******以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
#####你需要记住的
-0 所有的csrf都不校验了
-1 request对象变成了新的request对象,drf的request对象
-2 执行了权限,频率,认证
-3 捕获了全局异常(统一处理异常)
-4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
-5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
4.Request对象分析
1 django 原生的Request:django.core.handlers.wsgi.WSGIRequest
2 drf的Request:rest_framework.request.Request
3 drf的request对象内有原生的request
request._request:原生的Request
4 在视图类中使用
request.method 拿到的就是请求方式,
正常拿,应该request._request.method
5 如何实现这种操作?
-对象.属性会触发 类的__getattr__方法
6 drf的Request类重写了__getattr__
def __getattr__(self, attr):
try:
# 去原生的request反射属性
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
-request.data #post请求提交的数据,不论什么格式,都在它中
-requst.query_params# get请求提交的数据(查询参数)
8 重点记住:
-drf的request对象用起来跟原来一样(重写了__getattr__)
-request.data #post请求提交的数据,不论什么格式,都在它中
-requst.query_params# get请求提交的数据(查询参数)
5.序列化器介绍和使用
1 序列化:把python中的对象转成json格式字符串
2 反序列化:把json格式字符串转成python中的对象
3 注意:drf的序列化组件(序列化器)
把对象(Book,queryset对象)转成字典
因为有字典,直接丢到Response中就可以了
1 写一个序列化的类,继承Serializer
class BookSerializer(serializers.Serializer):
# 在这里写要序列化的字段
# 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
# 字段类,有很多字段参数()
name = serializers.CharField()
price = serializers.IntegerField()
# publish = serializers.CharField()
2 在类中写要序列化的字段
name = serializers.CharField()
price = serializers.IntegerField()
3 在视图类中使用(实例化)
book_list = models.Book.objects.all()
book_ser=BookSerializer(instance=book_list,many=True)
4 得到序列化后的数据,返回
book_ser.data
5 字段参数,source,指定要序列化表中的哪个字段
5.1 source
1 指定要序列化的字段(数据表中字段)
publish = serializers.CharField(source='publish.city')
2 指定方法
3 深度表查询
2 用的最多:只有一个字段(也可以跨表)
5.2 SerializerMethodField
1 用的最多,跨表查(要么是列表,要么是字典)
publish=serializers.SerializerMethodField()
def get_publish(self,obj):
return {'name':obj.publish.name,'city':obj.publish.city}
authors = serializers.SerializerMethodField()
def get_authors(self, obj):
return [{'name':author.name, 'age': author.age} for author in obj.authors.all()]
在模型表中写方法
# 表模型中写的
def publish_name(self):
return {'name':self.publish.name,'city':self.publish.city}
@property
def author_list(self):
return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
#序列化类中
# publish = serializers.CharField(source='publish_name')
publish_name = serializers.DictField()
author_list=serializers.ListField()