上节回顾
1 web开发模式:前后端分离(接口,drf),前后端混合(dtl)
jsp,JavaScript
2 api接口
- 接口,后端接口:给一个地址,向地址发送请求,可以返回json格式数据
3 restful规范
- 10 条:只是一个规范,不强制,所以公司有自己的规则
- 使用https:http+ ssl
- 路径中带api标识
- 路径中带版本号
- 尽量用名词加复数
- 通过请求方式来决定操作(get获取时间)
- 返回中带状态码(json数据带状态码:自己定义的,http响应中带状态码)
- 返回结果中带错误信息
- 请求地址中带查询条件
- 响应结果中带链接
4 postman的使用(接口测试)
- 模拟发送http请求,携带数据(请求地址,请求头,请求体,编码格式)
- 快速把接口导入导出
5 drf:djangorestframework,只针对于django,app,让我们快速的写接口,render,redirect了,只返回给前端json格式数据,前端可以是web,可以是app,可以是小程序
6 bbs作业
- 修改头像
- 不能使用update,要使用对象. save
- 是否发送邮件
- 只需要在Userinfo表加一个字段即可
补充:
- 在公司的开发环境
- windows:远程连接linux开发
- 乌班图。。。(图形化界面的linux)
- mac
-
今日内容
0 drf快速使用
0.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 ( )
0.2 serializer.py
from rest_framework. serializers import ModelSerializer
from app import models
class BookSerializer ( ModelSerializer) :
class Meta :
model = models. Book
fields = '__all__'
0.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
0.4 在setting的app中配置
INSTALLED_APPS = [
'rest_framework'
]
0.5 models.py
class Book ( models. Model) :
name = models. CharField( max_length= 32 )
publish = models. CharField( max_length= 32 )
price = models. IntegerField( )
1 CBV源码分析和APIView源码分析
1.1 cbv执行流程
path( 'test/' , views. TestView. as_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)
'''
1.2 APIView的执行流程
'''
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
'''
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
)
- 0 所有的csrf都不校验了
- 1 request对象变成了新的request对象,drf的request对象
- 2 执行了权限,频率,认证
- 3 捕获了全局异常(统一处理异常)
- 4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
- 5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
2 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 :
return getattr ( self. _request, attr)
except AttributeError:
return self. __getattribute__( attr)
7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
- request. data
- requst. query_params
8 重点记住:
- drf的request对象用起来跟原来一样(重写了__getattr__)
- request. data
- requst. query_params
3 序列化器的作用
1 序列化:把python中的对象转成json格式字符串
2 反序列化:把json格式字符串转成python中的对象
3 注意:drf的序列化组件(序列化器)
把对象(Book,queryset对象)转成字典
因为有字典,直接丢到Response中就可以了
4 序列化器的使用
1 写一个序列化的类,继承Serializer
class BookSerializer ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
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, 指定要序列化表中的哪个字段
4.2 source
1 指定要序列化的字段(数据表中字段)
publish = serializers. CharField( source= 'publish.city' )
2 用的最多:只有一个字段(也可以跨表)
4.2 SerializerMethodField
1 用的最多,跨表查(要么是列表,要么是字典)
publish= serializers. SerializerMethodField( )
def get_publish ( self, obj) :
print ( obj)
return { 'name' : obj. publish. name, 'city' : obj. publish. city}
4.3 在模型表中写方法
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_name = serializers. DictField( )
author_list= serializers. ListField( )
作业
0 CBV和APIView源码整理
1 drf的Resquest对象整理
2 查询一本书和所有书
[
{
"name" : "西游记" ,
"price" : 12 ,
"publish" : {
"id" : 1
"name" : "北京出版社" ,
"city" : "北京"
} ,
"authors" : [
{
"name" : "lqz" ,
"age" : 222 ,
"id" : 1
} ,
{
"name" : "egon" ,
"age" : 44 ,
"id" : 2
}
} ]
3 查询所有出版社和一个出版社
4 查询所有和一个作者