Django 是一个由 Python 编写的开放源代码的 Web 框架。使用 Django,只要很少的代码,Python 开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务
Django 本身基于 MVT 模式。MVT 模式本质上和 MVC 是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django 的 MVT分别是指:
补充 MVC 模式
模型(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。
视图(View)能够实现数据有目的的提示
控制器(Controller)起到不同层面的组织作用,用于控制应用程序的流程。处理事件并作出响应。”事件“包括用户的行为和数据Model上的改变。
http请求 -> 【uWSGI/wsig】 -> 【url】 -> 【view】 -> 【model & template】 -> 【uWSGI/wsig】-> 浏览器
WSGI(Web Server Gateway Interface,即Web服务器网关接口)是Python定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
它是Python为了解决Web服务器端与客户端之间的通信问题而产生的,它基于现存的CGI标准而设计。
其定义了Web服务器如何与Python应用程序进行交互,让Python写的Web应用程序可以和Web服务器对接起来。
请求走到WSGIHandler类的时候,执行cell方法,将environ封装成了request。
class WSGIHandler(base.BaseHandler):
request = self.request_class(environ)
中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变 Django 的输入或输出。
每个中间件组件都负责做一些特定的功能,常见的中间件有:
WSGI监听HTTP请求 ----> 将请求交给Handler处理 ---->
Web框架的本质是socket服务器,而用户的浏览器就是一个socket客户端,基于请求做出响应。客户端按照http协议发送请求,服务端做出对应的响应。
restful是一种软件架构设计风格,并不是标准,它只是提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。
就像设计模式一样,并不是一定要遵循这些原则,而是基于这个风格设计的软件可以更简洁,更有层次,我们可以根据开发的实际情况,做相应的改变。
它里面提到了一些规范,例如
1.restful 提倡面向资源编程,在url接口中尽量要使用名词,不要使用动词
2.在url接口中推荐使用Https协议,让网络接口更加安全
3.可以根据Http不同的method,进行不同的资源操作
4.在url中可以体现版本号
5.url中可以体现是否是API接口
6.url中可以添加条件去筛选匹配
7.响应式应该设置状态码
8.有返回值,而且格式为统一的json格式
9.返回错误信息
10.返回结果中要提供帮助链接,即API最好做到Hypermedia
Django在创建对象时在调用save()方法后,ORM框架会把对象的属性写入到数据库中,实现对数据库的初始化。
通过操作对象,查询数据库,将查询集返回给视图函数,通过模板语言展现在前端页面。
Django根据设置的缓存方式,浏览器第一次请求时,cache会缓存单个变量或整个网页等内容到硬盘或者内存中,同时设置response头部。
当浏览器再次发起请求时,附带f-Modified-Since请求时间到Django。
Django发现f-Modified-Since会先去参数之后,会与缓存中的过期时间相比较,如果缓存时间比较新,则会重新请求数据,并缓存起来然后返回response给客户端。
如果缓存没有过期,则直接从缓存中提取数据,返回给response给客户端。
ASGI是异步网关协议接口,一个介于网络协议服务和Python应用之间的标准接口,能够处理多种通用的协议类型,包括HTTP,HTTP2和WebSocket。
WSGI是基于HTTP协议模式的,不支持WebSocket,而ASGI的诞生则是为了解决Python常用的WSGI不支持当前Web开发中的一些新的协议标准。
同时,ASGI对于WSGI原有的模式的支持和WebSocket的扩展,即ASGI是WSGI的扩展。
django实现websocket使用channels。
channels通过http协议升级到websocket协议,保证实时通讯。
也就是说,我们完全可以用channels实现我们的即时通讯,而不是使用长轮询和计时器方式来保证伪实时通讯。
他使用asgi协议而不是wsgi协议,他通过改造django框架,使django既支持http协议又支持websocket协议。
name:给路由起一个别名
namespace:防止多个应用之间的路由重复
include用作路由转发,通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。
状态码:302,301
make migrations:生成迁移文件
migrate:执行迁移
程序很难100%保证数据的完整性,而用外键即使在数据库服务器宕机或异常的时候,也能够最大限度的保证数据的一致性和完整性。
如果项目性能要求不高,安全要求高,建议使用外键,如果项目性能要求高,安全自己控制,不用外键,因为外键查询比较慢。
加入外键的主要问题就是影响性能,因此加入索引能加快关联查询的速度。
有6种处理方式:
同时删除父表和子表
CASCADE:代表删除联级,父表(少类表)被删除的记录在子表(多类表)中所有字段也会被对应删除,模拟SQL语言中的ON DELETE CASCADE约束,将定义有外键的模型对象同时删除!(该操作为当前Django版本的默认操作!)
阻止删除父表
PROTECT:阻止上面的删除操作,但是弹出ProtectedError异常
子表设置为空
SET_NULL:代表父表(少类表)被删除后子表(多类表)对应的外键字段会设置为null,只有当字段设置了null=True,blank=True时,方可使用该值。
子表设置为默认值
SET_DEFAULT:代表父表(少类表)被删除后子表(多类表)对应的外键字段会设置为默认值。只有当字段设置了default参数时,方可使用。
子表什么都不做
DO_NOTHING:什么也不做,一切看数据库级别的约束
设置为一个传递给SET()的值或者一个回调函数的返回值
SET():设置为一个传递给SET()的值或者一个回调函数的返回值。注意大小写,用得很少。
# 查询人民邮电出版社出版并且价格大于50元的书籍
Book.objects.filter(publisher__name='人民邮电出版社').extra(where=['price>50'])
books=Book.objects.raw('select * from hello_book')
for book in books:
print(book)
from django.db import connection
cursor = connection.cursor()
cursor.execute("insert into hello_author(name) values ('特朗普')")
cursor.execute("update hello_author set name='普京' WHERE name='特朗普'")
cursor.execute("delete from hello_author where name='普京'")
cursor.execute("select * from hello_author")
cursor.fetchone()
cursor.fetchall()
ORM是“对象-关系-映射”的简称。
ORM是MVC或者MVC框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动。
程序员无需考虑数据库语句的操作,也无需考虑是什么数据库,只需要对 model 及进行操作即可实现增删改查。
增
# 创建、增加数据(推荐)
models.UserInfo.objects.create(username='root',password='123')
# 创建、增加数据
obj = models.UserInfo(username='xsk',password='123')
obj.save()
删
# 删除指定多个字段的行
models.UserInfo.objects.filter(username='root',password="123").delete()
改
# 修改指定字段内的所有值变为888
models.UserInfo.objects.all().update(password="888")
# 修改指定id的行修改字段内的值
models.UserInfo.objects.filter(id="3").update(password="777")
查
# 获取所有数据
result = models.UserInfo.objects.all()
# 只获取一条数据
obj = models.UserInfo.objects.first(id=nid).first()
Django 的 Queryset 主要有两个特性:一是惰性的(lazy),二是自带缓存的。
例如这个查询:
article_list = Article.objects.filter(title__contains="django")
在定义 article_list 的时候,Django的数据接口QuerySet并没有对数据库进行任何查询。无论你加多少过滤条件,Django都不会对数据库进行查询。只有当你需要对article_list做进一步运算时(比如打印出查询结果,判断是否存在,统计查询结果长度),Django才会真正执行对数据库的查询。这样设计的本意是尽量减少对数据库的无效操作,比如查询了结果而不用是计算资源的很大浪费。
在例1中,当你遍历queryset(article_list)时,所有匹配的记录会从数据库获取。这些结果会载入内存并保存在queryset内置的cache中。这样如果你再次遍历或读取这个article_list时,Django就不需要重复查询了,这样也可以减少对数据库的查询。
FBV(function base views) 就是在视图里使用函数处理请求。CBV(class base views) 就是在视图里使用类处理请求。Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。
CVB 主要优点:
FVB 主要优点:
继承方式有:
它们的区别如下:
Django不会为抽象模型在数据库中生成自己的数据表。父类Meta中的abstract=True也不会传递给子类。如果你发现多模型有很多共同字段时,需使用抽象模型继承。
多表模型继承与抽象模型继承最大的区别在于Django也会为父类模型建立自己的数据表,同时隐式地在父类和子类之间建立一个一对一关系。
如果我们只想改变某个模型的行为方法,而不是添加额外的字段或创建额外的数据表,我们就可以使用代理模型(proxy model)。设置一个代理模型,需要在子类模型Meta选项中设置proxy=True, Django不会为代理模型生成新的数据表。
一、django面试题(21道)
1、什么是wsgi?
2、django请求的生命周期?
3、列举django的内置组件?
4、列举django中间件的5个方法?以及django中间件的应用场景?
5、简述什么是FBV和CBV?
6、django的request对象是在什么时候创建的?
7、如何给CBV的程序添加装饰器?
8、列举django orm 中所有的方法(QuerySet对象的所有方法)
9、select_related和prefetch_related的区别?
10、filter和exclude的区别?
11、列举django orm中三种能写sql语句的方法
12、values和values_list的区别?
13、cookie和session的区别?
14、如何使用django orm批量创建数据?
15、django的Form组件中,如果字段中包含choices参数,请使用两种方式实现数据源实时更新。
16、django的Model中的ForeignKey字段中的on_delete参数有什么作用?
17、django的模板中自定义filter和simple_tag的区别?
20、Django本身提供了runserver,为什么不能用来部署?(runserver与uWSGI的区别)
21、Django如何实现websocket?
二、Python面试宝典 - 基础篇 - 2020
参考连接: