Django Rest framework 框架
一、开发模式:
1. 普通开发方式(前后端放在一起写)
2. 前后端分离(前后台通过ajaxo交互)
后端(django rest framework写的) <----ajaxo---> 前端(vue写的) <----- > 用户
好处:
二、后端开发
为前端提供url(API的开发或者接口的开发)
注:永远返回HttpResponse
路由
from django.conf.urls import url
from django.contrib import admin from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^users/', views.users),
]
视图 ( FBV:function base view 基于函数的视图 如下)
import json from django.shortcuts import render,HttpResponse # Create your views here. def users(request):
user_list = ['zgr','oldboy']
return HttpResponse(json.dumps(user_list))
后端的开发 http://127.0.0.1:8000/users/ 只要访问这个URL就返回所有用户列表如下: 这就是接口的开发!

三、Django中的FBV和CBV
FBV:function base view 基于函数的视图
函数作为视图函数
当访问URL时,函数执行了
CBV:class base view 基于类的视图 基于反射实现根据请求方式不同,执行不同的方法。
当访问URL的时候,这个类里面还可以写很多方法,这个类里那个方法被执行了?先.这个类再点这个方法。函数嵌套类里面。如果以GET 方式请求,就会执行get方法就会自动会被执行。
视图:
# 这个类必须继承django的这个View
from django.views import View class StudentsView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('GET') def post(self, request, *args, **kwargs):
return HttpResponse('POST') def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE') def put(self, request, *args, **kwargs):
return HttpResponse('PUT') def putch(self, request, *args, **kwargs):
return HttpResponse('PUTCH')
路由:
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),# 路由这里必须是类.as_view() 这是固定搭配
url(r'^students/', views.StudentsView.as_view()),
]
这样一个CBV就写完了。以不同的方式来执行,就会有不同的函数自动帮你执行了。
HTTP请求的本质基于socket来做的,浏览器发一个请求本质上发了一堆字符串/r/n分割 ,做路由匹配,匹配成功,如果是FBV的话执行它对应的函数。但是如果是CBV怎么找到方法?通过反射!
反射
什么是反射?
用在属性操作,之前是通过点操作属性。
在python3中,统一了类与类型的概念(定义一个类就是一个类型,基本的数据类型字符串,列表。。。都是类)。
通过字符串来反射到真正的属性身上,来进行属性操作。---->通过字符串来操作类或对象的属性。
让客户自己输入要执行的操作,输入的是字符串,就要用字符串来反射到真正的属性(数据属性,函数属性...)身上.
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,这四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
isinstance 用它来判断是否是一个实例。也可以用来判断数据类型
issubclass 判断一个类是否是另一个类的子类。
在python3中,统一了类与类型的概念(定义一个类就是一个类型,基本的数据类型字符串,列表。。。都是类)。
Python中一切皆对象。
class Foo(object):
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
obj = Foo()
# #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func')
# #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func')
# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')
d、比较三种访问方式
- obj.name
- obj.__dict__['name']
- getattr(obj, 'name')
四、列表生成式
class Foo:
pass class Bar:
pass v=[item() for item in [Foo,Bar]]
print(v) v就是对象列表里面,就是Foo的对象和Bar的对象。 打印结果:
[<__main__.Foo object at 0x1029d1358>, <__main__.Bar object at 0x1029d1320>]
v=[]
for i in [Foo,Bar]:
obj=i()
v.append(obj)
五、面向对象编程 类 封装
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

- class是关键字,表示类
- 创建对象,类名称后加括号即可
面向对象三大特性
一、封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
- 将内容封装到某处
- 从某处调用被封装的内容
第一步:将内容封装到某处

# 对同一类方法封装到了同一类里面
class File:
文件的增删改查 class DB:
数据库的增删改查 # 将数据封装到对象中(一个类实例化就是执行类的init方法得到一个对象)
class File:
def __init__(self,a1,a2): # self=obj
self.a1=a1 #obj.a1=a1
self.xxx=a2 #obj.xxx=a2
def get..
def put..
def delete..
def post.. obj1 = File(123,234)
self 是一个形式参数,当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1
当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj1 = Foo('wupeiqi', 18)
print obj1.name # 直接调用obj1对象的name属性
print obj1.age # 直接调用obj1对象的age属性
obj2 = Foo('alex', 73)
print obj2.name # 直接调用obj2对象的name属性
print obj2.age # 直接调用obj2对象的age属性
2、通过self间接调用被封装的内容
执行类中的方法时,需要通过self间接调用被封装的内容
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def detail(self):
print self.name
print self.age
obj1 = Foo('wupeiqi', 18)
obj1.detail() # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
obj2 = Foo('alex', 73)
obj2.detail() # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。
req.obj是Auth对象
class Request(object):
def __init__(self, obj):
self.obj = obj class Auth(object):
def __init__(self, name, age):
self.name = name
self.age = age class APIView(object):
def dispatch(self):
self.f2() def f2(self):
a = Auth('zrg', 18)
req = Request(a)
print(req.obj) obj = APIView()
obj.dispatch()
类似源码
class Request(object):
def __init__(self, obj): #req a
self.obj = obj #req.a=a @property #执行时不用加括号
def user(self): #第三步 req.obj.authenticate()=a.authenticate()
return self.obj.authenticate() class Auth(object):
def __init__(self, name, age): #a,zrg,18
self.name = name #a.name=zrg,a.age=18
self.age = age def authernticate(self): #第四步 a.name
# return True
# 在源码里
return self.name class APIView(object):
def dispatch(self): #传入对象自己obj
self.f2() #obj.f2() def f2(self):
a = Auth('zrg', 18) #第一步 实例化得到Auth对象a,把'zrg', 18封装进去 可以a.name a.age a.authernticate()
req = Request(a) #第二步 实例化得到Request对象 req Request里面有个obj是Auth的对象a 可以req.obj req.user
print(req.user) #第五步 对象里有什么就能点出来什么! obj = APIView() #实例得到APIView的对象obj
obj.dispatch() #执行对象的dispatch方法
CBV
框架基于反射来实现--->根据method的不同执行不同的方法。
反射的代码写在哪里?在View里面!
在路由系统里面永远是URL对应一个函数,类的对应的是这样的:

自己当前请求的类里面没有as_view方法,

没有去父类找,找到了。并且返回了个view

所以在路由那里执行as_view实际上是执行view方法,只不过这个函数里面有了cls,就是当前请求的类,类后面加括号,就是把这个类实例化

所以相当于self = StudentsView(),实例化对象,指定dispatch方法,并有返回值,就是HttpResponse,render.....(因为视图函数要么返回。。。。)

所以谁定义了dispatch,在定义的dispatch里面也有那些返回值。所以对CBV来说请求进来,执行里面的view函数可以忽略掉,直接执行dispatch。(不管什么请求进来都执行dispatch)
class StudentsView(View):
def dispatch(self, request, *args, **kwargs):
# request.method #可以获得请求方法
func = getattr(self,request.method.lower()) #去这个对象里面通过反射找到他不同的方法
ret = func(request, *args, **kwargs) #找到不同的方法可以执行一下,把它的参数都传进去。要有返回值,返回给客户
return ret
# return HttpResponse('父类的dispatch') def get(self, request, *args, **kwargs):
return HttpResponse('GET') def post(self, request, *args, **kwargs):
return HttpResponse('POST') def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE') def put(self, request, *args, **kwargs):
return HttpResponse('PUT') def putch(self, request, *args, **kwargs):
return HttpResponse('PUTCH')
但是以上代码不用自己写,父类(view)的的dispatch已经写好了

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
CBV原理跟流程:路由----->view方法------>dispatch方法(根据反射执行其他方法,get,post,put......)。
如果自己当前类自己有dispatch方法,父类不会执行,但是如果想让父类执行dispatch方法怎么做?
class StudentsView(View):
def dispatch(self, request, *args, **kwargs):
ret = super(StudentsView,self).dispatch(request, *args, **kwargs) #父类的dispatch方法会反射不同的方式,ret就是HttpResponse(请求对象)
return ret
执行顺序是这样的,
class StudentsView(View):
print('before')
def dispatch(self, request, *args, **kwargs):
print('before')
ret = super(StudentsView,self).dispatch(request, *args, **kwargs) #父类的dispatch方法会反射不同的方式,ret就是HttpResponse(请求对象)
print('after')
return ret def get(self, request, *args, **kwargs):
return HttpResponse('GET') def post(self, request, *args, **kwargs):
return HttpResponse('POST') def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE') def put(self, request, *args, **kwargs):
return HttpResponse('PUT') def putch(self, request, *args, **kwargs):
return HttpResponse('PUTCH')
所有请求来了先执行before,在执行视图函数,在执行after。--->跟装饰器相似
class StudentsView(View):def dispatch(self, request, *args, **kwargs):
print('before')
ret = super(StudentsView,self).dispatch(request, *args, **kwargs) #父类的dispatch方法会反射不同的方式,ret就是HttpResponse(请求对象)
print('after')
return ret
假如还有很多什么什么view,如果都需要先做before年最后做after,在下面写视图的时候,又得拷贝一遍。怎么办?
写个基类,继承(多个类公用的功能,为了避免重复编写)。多继承左边优先。
class MyBaseView(object):
def dispatch(self, request, *args, **kwargs):
print('before')
ret = super(MyBaseView,self).dispatch(request, *args, **kwargs) #父类的dispatch方法会反射不同的方式,ret就是HttpResponse(请求对象)
print('after')
return ret
class StudentsView(MyBaseView,View): def get(self, request, *args, **kwargs):
print('get方法')
return HttpResponse('GET') def post(self, request, *args, **kwargs):
return HttpResponse('POST') def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE') def put(self, request, *args, **kwargs):
return HttpResponse('PUT') def putch(self, request, *args, **kwargs):
return HttpResponse('PUTCH')
super不是简单的只找父类,会根据super(MyBaseView,self)这个self对象整个的继承关系找到下一个继承对象里的方法。
Django请求生命周期:
请求进来先走wsgi--->中间件------>视图(FBV/CBV)----->如果是cbv进来走dispatch,然后反射找到试图函数返回。
Django请求生命周期(包含rest framework框架):
请求进来先走wsgi--->中间件------>视图(FBV/CBV)----->如果是cbv进来走dispatch,然后反射返回。---->重新写成Django的rest framework的dispatch了(添加了一部分功能)。
ps:dispatch
Django Rest framework 框架的更多相关文章
- Django REST framework框架介绍和基本使用
Django REST framework介绍 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官 ...
- Django Rest framework 框架之认证使用和源码执行流程
用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...
- Django Rest Framework框架 ---- url控制器
Django Rest Framework框架 ---- url控制器
- web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝
web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...
- web前端Vue+Django rest framework 框架 生鲜电商项目实战✍✍✍
web前端Vue+Django rest framework 框架 生鲜电商项目实战 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频 ...
- Django Rest Framework框架源码流程
在详细说django-rest-framework源码流程之前,先要知道什么是RESTFUL.REST API . RESTFUL是所有Web应用都应该遵守的架构设计指导原则. REST是Repres ...
- Django rest framework框架中有哪些组件
认证 权限(授权) 用户访问次数/频率限制 版本 解析器(parser) 序列化 分页 路由系统 视图 渲染器 认证 自定义认证的类 """ from rest_fram ...
- Django Rest framework 框架之解析器
解析器 序列化***** 请求数据进行校验 对queryset进行序列化处理 分页 路由 视图 渲染器
- Django rest framework框架——APIview源码分析
一.什么是rest REST其实是一种组织Web服务的架构,而并不是我们想象的那样是实现Web服务的一种新的技术,更没有要求一定要使用HTTP.其目标是为了创建具有良好扩展性的分布式系统. 可用一句话 ...
随机推荐
- 获取列表的索引操作:enumerate
通过循环获取列表的索引操作: 主要使用:enumerate product_list = [['Iphone7',5800], ['Coffee',30], ['疙瘩汤',10], ['Python ...
- Linux下简单的缓冲区溢出
缓冲区溢出是什么? 科班出身,或者学过汇编的应该知道,当缓冲区边界限制不严格时,由于变量传入畸形数据或程序运行错误,导致缓冲区被“撑爆”,从而覆盖了相邻内存区域的数据 成功修改内存数据,可造成进程劫持 ...
- Python 中的浅拷贝和深拷贝
1. 列表和字典,直接赋值,都是浅拷贝,即赋值双方指向同一地址,因为 Python 对可变对象按引用传递. >>> a = [1, 2, 3] >>> b = a ...
- leetcode 704. Binary Search 、35. Search Insert Position 、278. First Bad Version
704. Binary Search 1.使用start+1 < end,这样保证最后剩两个数 2.mid = start + (end - start)/2,这样避免接近max-int导致的溢 ...
- Java类文件结构详解
概述: Class文件结构是了解虚拟机的重要基础之一,如果想深入的了解虚拟机,Class文件结构是不能不了解的.Class文件是一组以8位字节为基础单位的二进制流,各项数据项目严格按照顺序紧凑地排列在 ...
- Java验证工具类
在项目中使用Java经常有验证功能的使用,比如手机号,密码等验证. 总结一下,写出个工具类方便以后用的时候直接引. package com.common.utils; import org.apach ...
- Java之所有输入流输出流的分类
(1)字节输入流 基类:InputStream FileInputStream.ByteArrayInputStream.PipedInputStream.Buffered ...
- 【C#复习总结】细说表达式树
1 前言 系类1:细说委托 系类2:细说匿名方法 系列3:细说Lambda表达式 系列4:细说泛型委托 系列5:细说表达式树 系列6:细说事件 涛声依旧,再续前言,接着用大佬的文章作为开头. 表达式树 ...
- IDEA报错Error:Module 'shop-common' production: java.lang.IndexOutOfBoundsException
问题描述: 本来项目是正常的,编译.运行.启动都是OK的,但是在一次电脑重启后,出现了以上这个问题:Error:Module 'shop-common' production: java.lang.I ...
- 朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP
阅读PDF版本 标题有点标题党了,这里说的容易犯错不是Spring AOP的错,是指使用的时候容易犯错.本文会以一些例子来展开讨论AOP的使用以及使用过程中容易出错的点. 几句话说清楚AOP 有关必要 ...