Hello,我是 Alex 007,为啥是007呢?因为叫 Alex 的人太多了,再加上每天007的生活,Alex 007就诞生了。
框架层
01.什么是Django框架?(初级)
Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式。使用这种架构,程序员可以方便、快捷地创建高品质、易维护、数据库驱动的应用程序。它还包含许多功能强大的第三方插件,使得Django具有较强的可扩展性。
02.Django对web开发有哪些优势?(初级)
-
功能完善、要素齐全:该有的、可以没有的都有,自带大量常用工具和框架,无须你自定义、组合、增删及修改。
-
完善的文档:经过十多年的发展和完善,Django有广泛的实践案例和完善的在线文档。开发者遇到问题时可以搜索在线文档寻求解决方案。
-
强大的数据库访问组件:Django的Model层自带数据库ORM组件,使得开发者无须学习其他数据库访问技术(SQL、pymysql、SQLALchemy等)。
-
灵活的URL映射:Django使用正则表达式管理URL映射,灵活性高。新版的2.0,进一步提高了URL编写的优雅性。
-
丰富的Template模板语言:类似jinjia模板语言,不但原生功能丰富,还可以自定义模板标签,并且与其ORM的用法非常相似。
-
自带后台管理系统admin:只需要通过简单的几行配置和代码就可以实现一个完整的后台数据管理控制平台。
-
完整的错误信息提示:在开发调试过程中如果出现运行错误或者异常,Django可以提供非常完整的错误信息帮助定位问题。
03.简述Django项目的组成模块(初级)
Project:工程是承载了Django实例的所有设置的Python程序包。
大部分情况下,一个Web站点就是一个工程。工程内可以新建及存放该工程固有的应用,或者保存Web站点的设置(数据库设置、Django的选项设置、各应用的设置等)
Apps:对于Django而言,应用之的是表示单一工程的Web应用的Python程序包。
由于其本质就是Python程序包,因此方法PYTHONPATH有效地任何位置都没有问题。这里最好尽量减少应用与工程、应用于应用之间的依赖关系,做到功能独立,以便在其他工程中重复利用。
Model:Django提供了O/R映射工具,因此可以用Python代码来描述数据库布局。
每个模型都是继承了django.db.models.Model类的Python的类,分别对应数据库中的一个表格。通过建数据库的字段、关系、行为定义为模型类的属性或方法,我们可以使用丰富且灵活的数据库方位API。
URL Route:URL分配器机制使得URL信息不再受框架及扩展名的制约,从而让Web应用的URL设计保持简介。
URl在URlconf模块中进行描述,URLconf模块中包含使用正则表达式书写的URL和Python函数的映像。URlconf能够以应用为单位进行分割,因此提高了应用的可重复利用性。另外,我们可以利用给URL设置名称并定义的方式让代码和目标直接通过该名称调用URL,从而将URL设计与代码分离。
View:Django的视图时一类函数,它能够生成指定页面的HttpResponse对象或像Http 404这样的异常情况,返回HTTP请求。
典型的视图函数的处理流程通常是从请求参数中获取数据,读取模型,热按后根据获取的数据渲染模板。
DTL:在Django的概念中,模板系统只负责显示,并不是编写逻辑代码的环境。
因此Django的模板系统将设计与内容、代码分离开来,是一共功能强、扩展性高、对设计者很友好的模板语言。
模板基于文本而不是XML,因此它不但能生成XML和HTML,还能生成E-mail、JavaScript、CSV等任意文本格式。
另外,如果使用模板继承功能,子模板只需要将父模板中预留的空位填满即可。我们在编写模板时只需要描述各个模板独有的部分,因此可以省去重复冗余的编码过程。
Admin:大多Web应用在运行过程中,都需要一个专供拥有管理员权限的用户添加、编辑、删除数据的界面,但是实际制作这个界面并不容易。
Django只需将已经完工的模型添加到管理站点,就能根据模型定义,动态地生成页面。为我们提供一个功能齐全的管理界面。
Cache System:Django可以使用memcached等缓存后端轻松地缓存数据。
比如可以将动态页面的渲染结果缓存下来,等到下次需要时直接读取缓存,从而不必每次都对动态页面进行处理。
缓存的后端可以从memcached、数据库、文件系统、本地内存等位置进行选择。缓存对象也支持整个网站、特定的整个视图、部分模板、特定数据等。
04.简述MVC模式和MVT模式(初级)
MVC就是把Web应用分为模型(M),控制器C和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求。
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是:
M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
T 代表模板 (Template):负责如何把页面展示给用户(html)。
V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式。
05.简述Django请求生命周期(初级)
-
uWSGI服务器通过wsgi协议,将HttpRequest交给web框架 (Flask、Django)
-
首先到达request中间件,对请求对象进行校验或添加数据,例如:csrf、request.session,如果验证不通过直接跳转到response中间件
-
过URL配置文件找到urls.py文件
-
根据浏览器发送的URL,通过视图中间件去匹配不同的视图函数或视图类,如果没有找到相对应的视图函数,就直接跳转到response中间件
-
在视图函数或视图类中进行业务逻辑处理,处理完返回到response中间件
-
模型类通过ORM获取数据库数据,并返回序列化json或渲染好的Template到response中间件
-
所有最后离开的响应都会到达response中间件,对响应的数据进行处理,返回HttpResponse给wsgi
-
wsgi经过uWSGI服务器,将响应的内容发送给浏览器。
07.什么是WSGI?(初级)
WSGI(Web Server Gateway Interface,即Web服务器网关接口)是Python定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
它是Python为了解决Web服务器端与客户端之间的通信问题而产生的,它基于现存的CGI标准而设计。
其定义了Web服务器如何与Python应用程序进行交互,让Python写的Web应用程序可以和Web服务器对接起来。
08.uwsgi、uWSGI和WSGI的区别?(中级)
-
uwsgi:是uWSGI服务器实现的独有协议,用于Nginx服务与uWSGI服务的通信规范
-
uWSGI:是一个Web服务器,它实现了WSGI/uwsgi/HTTP等协议,用于接收Nginx转发的动态请求,处理后发个python应用程序
-
WSGI:用在python web框架(Django/Flask)编写的应用程序与web服务器之间的规范
09.Django的HttpRequest对象是在什么时候创建的?(中级)
class WSGIHandler(base.BaseHandler):
request = self.request_class(environ)
请求走到WSGIHandler类的时候,执行cell方法,将environ封装成了request。
10.什么是中间件并简述其作用(初级)
中间件是一个用来处理Django请求和响应的框架级钩子。
它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。
每个中间件组件都负责做一些特定的功能。
11.列举django中间件的5个方法,以及django中间件的应用场景(初级)
process_request : 请求进来时,权限认证
process_view : 路由匹配之后,能够得到视图函数
process_exception : 异常时执行
process_template_responseprocess : 模板渲染时执行
process_response : 请求有响应时执行
12.简述Django对http请求的执行流程(初级)
在接受一个Http请求之前的准备,需启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。
Django服务器根据WSGI协议指定相应的Handler来处理Http请求。
此时服务器已处于监听状态,可以接受外界的Http请求,当一个http请求到达服务器的时候,Django服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。
在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。
最后返回一个可以被浏览器解析的符合Http协议的HttpResponse。
13.Django中session的运行机制是什么?(初级)
django的session存储可以利用中间件来实现。
需要在 settings.py 文件中注册APP、设置中间件用于启动。
设置存储模式(数据库/缓存/混合存储)和配置数据库缓存用于存储,生成django_session表单用于读写。
14. 什么是CSRF,请描述其攻击原理,在Django中如何解决?(初级)
CSRF(cross-site request forgery)简称跨站请求伪造。
例如,你访问了信任网站A,然后网站A会用保存你的个人信息并返回给你的浏览器一个cookie。
然后呢,在cookie的过期时间之内,你去访问了恶意网站B,它给你返回一些恶意请求代码,要求你去访问网站A。
而你的浏览器在收到这个恶意请求之后,在你不知情的情况下,会带上保存在本地浏览器的cookie信息去访问网站A,然后网站A误以为是用户本身的操作。
这将导致来自恶意网站C的攻击代码会被执行:发邮件,发消息,修改你的密码,购物,转账,偷窥你的个人信息,导致私人信息泄漏和账户财产安全受到威胁。
在post请求时,form表单或ajax里添加csrf_token,服务端开启CSRF中间件进行验证。
解决原理是页面添加csrf_token值后,用户通过URL访问(GET请求)该页面时,Django会在响应中自动帮我们生成cookie信息,返回给浏览器,同时在前端代码会生成一个csrf_token值。
然后当你POST提交信息时,Django会自动比对cookie里和前端form表单或ajax提交上来的csrf_token值,两者一致,说明是当前浏览器发起的正常请求并处理业务逻辑返回响应。
那么第三方网站拿到你的cookie值为什么不能通过验证呢?
因为他没你前端的那个随机生成的token值,他总不能跑到你电脑面前查看你的浏览器前端页面自动随机生成的token值吧。
15. Django中CSRF的实现机制(初级)
-
django第1次响应来自某个客户端的请求时,服务器随机产生1个token值,把这个token保存在session中;同时服务器把这个token放到cookie中交给前端页面;
-
该客户端再次发起请求时,把这个token值加入到请求数据或者头信息中,一起传给服务器;
-
服务器校验前端请求带过来的token和session里的token是否一致。
16.什么是跨域请求,其有哪些方式?(初级)
- 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源。
方式如下:
-
资源跳转: a链接、重定向、表单提交
-
资源嵌入: link/script/img/frame/dom等标签,还有样式中background:url()、@font-face()等文件外链
-
脚本请求: js发起的ajax请求、dom和js对象的跨域操作等
17.跨域请求Django是如何处理的?(初级)
使用第三方工具 django-cors-headers 即可彻底解决
-
注册app
-
添加中间件
-
配置运行跨域请求方法
16.什么是信号量?(初级)
Django包含一个"信号调度程序",它有助于在框架中的其他位置发生操作时通知分离的应用程序。
简而言之,信号允许某些发送者通知一组接收器已经发生了某些动作。
当许多代码可能对同一事件感兴趣时,它们特别有用。
17.web框架的本质是什么?(初级)
web框架本质是一个socket服务端,用户的浏览器是一个socket客户端。
18.谈谈你对restful规范的认识(初级)
restful是一种软件架构设计风格,并不是标准,它只是提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。
就像设计模式一样,并不是一定要遵循这些原则,而是基于这个风格设计的软件可以更简洁,更有层次,我们可以根据开发的实际情况,做相应的改变。
它里面提到了一些规范,例如
1.restful 提倡面向资源编程,在url接口中尽量要使用名词,不要使用动词
2.在url接口中推荐使用Https协议,让网络接口更加安全
3.可以根据Http不同的method,进行不同的资源操作
4.在url中可以体现版本号
5.url中可以体现是否是API接口
6.url中可以添加条件去筛选匹配
7.响应式应该设置状态码
8.有返回值,而且格式为统一的json格式
9.返回错误信息
10.返回结果中要提供帮助链接,即API最好做到Hypermedia
19.Django中如何加载初始化数据?(初级)
Django在创建对象时在调用save()方法后,ORM框架会把对象的属性写入到数据库中,实现对数据库的初始化。
通过操作对象,查询数据库,将查询集返回给视图函数,通过模板语言展现在前端页面。
20.Django缓存系统类型有哪些?(初级)
- 全站缓存,较少使用
MIDDLEWARE_CLASSES = (
‘django.middleware.cache.UpdateCacheMiddleware’, # 第一
'django.middleware.common.CommonMiddleware',
‘django.middleware.cache.FetchFromCacheMiddleware’, # 最后
)
- 视图缓存,用户视图函数或视图类中
from django.views.decorators.cache import cache_page
import time
@cache_page(15) #超时时间为15秒
def index(request):
t=time.time() #获取当前时间
return render(request,"index.html",locals())
- 模板缓存,指缓存不经常变换的模板片段
{% load cache %}
<h3 style="color: green">不缓存:-----{{ t }}</h3>
{% cache 2 'name' %} # 存的key
<h3>缓存:-----:{{ t }}</h3>
{% endcache %}
21.请简述Django下的(内建)缓存机制(初级)
Django根据设置的缓存方式,浏览器第一次请求时,cache会缓存单个变量或整个网页等内容到硬盘或者内存中,同时设置response头部。
当浏览器再次发起请求时,附带f-Modified-Since请求时间到Django。
Django发现f-Modified-Since会先去参数之后,会与缓存中的过期时间相比较,如果缓存时间比较新,则会重新请求数据,并缓存起来然后返回response给客户端。
如果缓存没有过期,则直接从缓存中提取数据,返回给response给客户端。
22.什么是ASGI,简述WSGI和ASGI的关系与区别?(初级)
ASGI是异步网关协议接口,一个介于网络协议服务和Python应用之间的标准接口,能够处理多种通用的协议类型,包括HTTP,HTTP2和WebSocket。
WSGI是基于HTTP协议模式的,不支持WebSocket,而ASGI的诞生则是为了解决Python常用的WSGI不支持当前Web开发中的一些新的协议标准。
同时,ASGI对于WSGI原有的模式的支持和WebSocket的扩展,即ASGI是WSGI的扩展。
23.Django如何实现websocket?(初级)
django实现websocket使用channels。
channels通过http协议升级到websocket协议,保证实时通讯。
也就是说,我们完全可以用channels实现我们的即时通讯,而不是使用长轮询和计时器方式来保证伪实时通讯。
他使用asgi协议而不是wsgi协议,他通过改造django框架,使django既支持http协议又支持websocket协议。
25.列举django的核心组件(初级)
-
用于创建模型的对象关系映射;
-
为最终用户设计较好的管理界面;
-
URL设计;
-
设计者友好的模板语言;
-
缓存系统。
26.Django本身提供了runserver,为什么不能用来部署?(初级)
-
runserver方法是调试 Django 时经常用到的运行方式,它使用Django自带的WSGI Server 运行,主要在测试和开发中使用,并且 runserver 开启的方式也是单进程。
-
uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http 等协议。
注意uwsgi是一种通信协议,而uWSGI是实现uwsgi协议和WSGI协议的 Web 服务器。
uWSGI具有超快的性能、低内存占用和多app管理等优点,并且搭配着Nginx就是一个生产环境了,能够将用户访问请求与应用 app 隔离开,实现真正的部署。
相比来讲,支持的并发量更高,方便管理多进程,发挥多核的优势,提升性能。
27.ajax请求的csrf解决方法(高级)
-
首先在你需要发起ajax post请求的页面的里面随便一个地方加上 {% crsr_token %}
-
在发起ajax post 请求时,组织json参数时,将浏览器cookie中的值赋予加入json中,键名为‘csrfmiddlewaretoken’
路由层
01.路由优先匹配原则是什么?(初级)
在url匹配列表中位置优先匹配
如第1条和第2条同时满足匹配规则,则优先匹配第1条。
如第1条为正则模糊匹配,第2条为精确匹配,也是优先匹配第1条
02.urlpatterns中的name与namespace的区别(初级)
name:给路由起一个别名
namespace:防止多个应用之间的路由重复
03.Django路由系统中include是干嘛用的?(初级)
include用作路由转发,通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。
04.Django2.x中的path与django1.x里面的URL有什么区别?(初级)
path与url是两个不同的模块,效果都是响应返回页面, path调用的是python第三方模块或框架,而url则是自定义的模块。
url默认支持正则表达式,而path不支持,正则表达式需要使用另外一个函数re_path。
05.Django重定向的几种方法,用的什么状态码?(初级)
-
HttpResponse
-
Redirect
-
Reverse
状态码:302,301
模型层
01.命令migrate 和makemigrations的差别?(初级)
-
makemigrations:生成迁移文件
-
migrate:执行迁移
02.Django的Model的继承有几种形式?(初级)
- 抽象继承
父类继承来自model.Model, 但不会在底层数据库生成相应的数据表,父类的属性存储在其子类的数据表中。
作用:多个表若有相同的字段时,可以将这些字段统一定义在抽象类中.
对于内联的Meta类的继承,一般的,父类的Meta类的属性会继承给子类,子类也可以在自己的Meta中重写或者拓展父类的Meta,拓展的话主要是继承父类的Meta。
- 多表继承
每个模型类都会在底层数据库中生成相应的数据表管理数据。
父类中的字段不会重复地在对个子类相关的数据表中进行定义。
- proxy model(代理model)
代理模型中子类只用于管理父类的数据,而不实际存储数据。
使用原因:子类中的新特性不会影响父类行为以及已有代码的行为。
03.class Meta中的元信息字段有哪些?(初级)
-
Model类可以通过元信息类设置索引和排序信息
-
元信息是在Model类中定义一个Meta子类
class Meta:
# ---常用
db_table = 'table_name' # 自定义表名
index_together = ('tag1', 'tag2') # 联合索引
unique_together = ('tag3', 'tag4') # 联合唯一索引
verbose_name = 'table_name' # /admin/中显示的表名称
verbose_name_plural = verbose_name
ordering = 'ordering_tag' # 排序字段#这个选项是指定,模型的复数形式是什么
abstract =True # 抽象基类
# ---非常用
# app_label这个选项只在一种情况下使用,就是你的模型类不在默认的应用程序包下的models.py文件中,
# 这时候你需要指定你这个模型类是那个应用程序的。
# 比如你在其他地方写了一个模型类,而这个模型类是属于myapp的
app_label='myapp'
# db_table 是用于指定自定义数据库表名的。
db_table='my_owner_table'
# 有些数据库有数据库表空间,比如Oracle。你可以通过db_tablespace来
# 指定这个模型对应的数据库表放在哪个数据库表空间。
db_tablespace
# 由于Django的管理方法中有个lastest()方法,就是得到最近一行记录。
# 如果你的数据模型中有 DateField 或 DateTimeField 类型的字段,
# 你可以通过这个选项来指定lastest()是按照哪个字段进行选取的
get_latest_by = "order_date"
# 由于Django会自动根据模型类生成映射的数据库表,如果你不希望Django这么做,可以把managed的值设置
# 为False。默认值为True,这个选项为True时Django可以对数据库表进行 migrate或migrations、
# 删除等操作。在这个时间Django将管理数据库中表的生命周期如果为False的时候,不会对数据库表进行
# 创建、删除等操作。可以用于现有表、数据库视图等,其他操作是一样的。
managed
# permissions主要是为了在Django Admin管理模块下使用的,如果你设置了这个属性可以让
# 指定的方法权限描述更清晰可读。要创建一个对象所需要的额外的权限. 如果一个对象有 admin 设置,
# 则每个对象的添加,删除和改变权限会人(依据该选项)自动创建.
# 下面这个例子指定了一个附加权限: can_deliver_pizzas:
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
# 这个选项一般用于多对多的关系中,它指向一个关联对象。就是说关联对象找到这个对象后它是经过排序的。
# 指定这个属性后你会得到一个get_XXX_order()和set_XXX_order()的方法,
# 通过它们你可以设置或者回去排序的对象。
order_with_respect_to = 'pizza'
04.Django模型类关系有哪几种?(初级)
-
一对一关系:OneToOneField
-
一对多关系:ForeignKey
-
多对多关系:ManyToManyField
05.外键有什么用,什么时候合适使用外键 ,外键一定需要索引吗?(中级)
-
程序很难100%保证数据的完整性,而用外键即使在数据库服务器宕机或异常的时候,也能够最大限度的保证数据的一致性和完整性。
-
如果项目性能要求不高,安全要求高,建议使用外键,如果项目性能要求高,安全自己控制,不用外键,因为外键查询比较慢。
-
加入外键的主要问题就是影响性能,因此加入索引能加快关联查询的速度。
Primary KeyUnique Key
-
Primary key与Unique Key都是唯一性约束。
-
Primary key是主键,一个表只能由一个,Unique key是唯一键,一个表可以有多个唯一键字段。
-
Primary key 必须不能为空,Unique Key 可为空。
auto_nowauto_now_add
- DateTimeField.auto_now 用于记录更新时间
这个参数的默认值为false,设置为true时,能够在保存该字段时,将其值设置为当前时间,并且每次修改model,都会自动更新。
因此这个参数在需要存储“最后修改时间”的场景下,十分方便。
需要注意的是,设置该参数为true时,并不简单地意味着字段的默认值为当前时间,而是指字段会被“强制”更新到当前时间,你无法程序中手动为字段赋值。
如果使用django再带的admin管理器,那么该字段在admin中是只读的。
- DateTimeField.auto_now_add 用于记录创建时间
这个参数的默认值也为False,设置为True时,会在model对象第一次被创建时,将字段的值设置为创建时的时间,以后修改对象时,字段的值不会再更新。
该属性通常被用在存储“创建时间”的场景下。
与auto_now类似,auto_now_add也具有强制性,一旦被设置为True,就无法在程序中手动为字段赋值,在admin中字段也会成为只读的。
08.当删除一个外键的时候,其关联的表有几种处理方式?(初级)
有6种处理方式:
- 同时删除父表和子表
CASCADE:代表删除联级,父表(少类表)被删除的记录在子表(多类表)中所有字段也会被对应删除,模拟SQL语言中的ON DELETE CASCADE约束,将定义有外键的模型对象同时删除!(该操作为当前Django版本的默认操作!)
- 阻止删除父表
PROTECT:阻止上面的删除操作,但是弹出ProtectedError异常
- 子表设置为空
SET_NULL:代表父表(少类表)被删除后子表(多类表)对应的外键字段会设置为null,只有当字段设置了null=True,blank=True时,方可使用该值。
- 子表设置为默认值
SET_DEFAULT:代表父表(少类表)被删除后子表(多类表)对应的外键字段会设置为默认值。只有当字段设置了default参数时,方可使用。
- 子表什么都不做
DO_NOTHING:什么也不做,一切看数据库级别的约束
- 设置为一个传递给SET()的值或者一个回调函数的返回值
SET():设置为一个传递给SET()的值或者一个回调函数的返回值。注意大小写,用得很少。
09.如何通过外键,子表查询父表和父表查询子表(中级)
父表和子表关系如下:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=64)
age = models.IntegerField()
tel = models.CharField(max_length=64)
@property
def all_cars(self):
'''返回全部信息'''
return self.cars.all()
@property
def info(self):
'''返回部分信息'''
return '%s %s' % (self.name, self.tel)
class Car(models.Model):
owner = models.Foreignkey(Person, related_name='cars')
name = models.CharField(max_length=64)
price = models.FloatField()
子表查询父表
car = Car.objects.get(id=1)
# 查询该车的车主
owner = car.owner
父表查询子表
Tom = Person.objects.get(id=1)
# 查询此人有多少车
# 方式一:
# Django默认每个主表对象都有一个外键的属性,可以通过它来查询所有属于主表的子表信息
# 查询方式:主表.子表_set(),返回值为一个queryset对象
Tom.Car_set().all()
# 方式二:
# 通过在外键中设置related_name属性值既可
Tom.cars.all()
# 方式三:
# 通过@property装饰器在model中预定义方法实现
Tom.all_cars
10.谈谈 GenericForeignkey 和 GenericRelation(高级)
GenericForeignkey 和 GenericRelation 的方法能够解决多外键的表单产生的大量沉余数据。
通过ContentType的查询,起到一个自动一对多的作用,能和任何模型都能连接起来,保证了代码的干净。
避免了创建大量无用的空数据,有效减少存储空间和服务器压力。
11.django中怎么写原生SQL?(中级)
- 使用extra
# 查询人民邮电出版社出版并且价格大于50元的书籍
Book.objects.filter(publisher__name='人民邮电出版社').extra(where=['price>50'])
- 使用raw
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()
12.谈一谈你对ORM的理解(中级)
ORM是“对象-关系-映射”的简称。
ORM是MVC或者MVC框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动。
13.如何使用Django ORM批量创建数据?(初级)
可以使用django.db.models.query.QuerySet.bulk_create()批量创建对象,减少SQL查询次数。
# 创建一个空列表
querysetlist=[]
# 把创建的对象添加入列表中
for i in resultlist:
querysetlist.append(Account(name=i))
# 批量创建
Account.objects.bulk_create(querysetlist)
14.列举django ORM中操作QuerySet对象的方法(至少5个)(初级)
方法 | 作用 |
---|---|
all() | 查询所有结果 |
filter() | 过滤查询对象。获取不到返回None。 |
get() | 返回与所给筛选条件相匹配的对象,返回结果有且只有1个。如果符合筛选条件的对象超过1个或者没有都会抛出错误。 |
exclude() | 排除满足条件的对象 |
order_by() | 对查询结果排序 |
reverse() | 对查询结果反向排序 |
count() | 返回数据库中匹配查询(QuerySet)的对象数量。 |
first() | 返回第一条记录 |
last() | 返回最后一条记录 |
exists() | 如果QuerySet包含数据,就返回True,否则返回False |
values() | 返回包含对象具体值的字典的QuerySet |
values_list() | 与values()类似,只是返回的是元组而不是字典。 |
distinct() | 对查询集去重 |
15.ORM如何取消级联?(初级)
user = models.ForeignKey(User,blank=True,null=True,on_delete=models.SET_NULL)
在父表被删除,null为True的时候就会取消级联。
16.查询集的2大特性?什么是惰性执行?(中级)
特性:
-
惰性执行
-
缓存
惰性执行是指创建查询集不会访问数据库,直到调用数据时,才会访问数据库。
17.查询集返回的列表过滤器有哪些?(中级)
all():返回所有数据
filter():返回满足条件的数据
exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字
order_by():排序
18.selected_related与prefetch_related有什么区别?(高级)
在Django中当创建一个查询集的时候,并没有跟数据库发生任何交互。
因此我们可以对查询集进行级联的filter等操作,只有在访问Queryset的内容的时候,Django才会真正进行数据库的访问。
而多频率、复杂的数据库查询往往是性能问题最大的根源。
不过我们实际开发中,往往需要访问到外键对象的其他属性。
如果按照默认的查询方式去遍历取值,那么会造成多次的数据库查询,效率可想而知。
在查询对象集合的时候,把指定的外键对象也一并完整查询加载,避免后续的重复查询。
使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能。
-
select_related适用于一对一字段(OneToOneField)和外键字段(ForeignKey)查询;
-
prefetch_related适用多对多字段(ManyToManyField)和一对多字段的查询。
19.values()与values_list()有什么区别?(初级)
values : 读取字典的Queryset
values_list : 读取元组的Queryset
20.QueryDict和dict区别?(高级)
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
在 HttpRequest 对象中,属性 GET 和 POST 得到的都是 django.http.QueryDict 所创建的实例。
这是一个django 自定义的类似字典的类,用来处理同一个键带多个值的情况。
在 python 原始的字典中,当一个键出现多个值的时候会发生冲突,只保留最后一个值。
而在 HTML 表单中,通常会发生一个键有多个值的情况,例如,多选框就是一个很常见情况。
request.POST 和request.GET 的QueryDict 在一个正常的请求/响应循环中是不可变的。
若要获得可变的版本,需要使用.copy()方法。
-
python dict当一个键出现多个值的时候会发生冲突,只保留最后一个值。
-
QueryDict是类似字典的自定义类,用来处理单键对应多值的情况。
21.Django中查询Q和F的区别?(中级)
Q查询:对数据的多个字段联合查询(常和且或非"& | ~"进行联合使用)
F查询:对数据的不同字段进行比较(常用于比较和更新,对数据进行加减操作)
视图层
01.简述什么是FBV和CBV(初级)
FBV(function base views)使用视图函数处理请求
CBV(class base views)使用视图类处理请求
02.如何给CBV的程序添加装饰器?(初级)
导入 method_decorator 装饰器
-
给方法加
-
给dispatch加
-
给类加
from django.utils.decorators import method_decorator
@method_decorator(check_login)
def post(self, request):
'''给方法加'''
...
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):
'''给dispatch加'''
...
@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):
'''给类加'''
...
03.常用视图响应的方式有哪些?(初级)
常用视图响应的方式有4种方式redirect、Response、HttpResponse和JsonResponse
return Response(content=响应体, content_type=响应体数据类型, status=状态码)
return HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
return JsonResponse({‘city’: ‘beijing’, ‘subject’: ‘python’},status=response.status_code)
return redirect(‘/index.html’)
04.在视图函数中,常用的验证装饰器有哪些?(中级)
装饰器 | 用途 |
---|---|
@login_required() | 检查用户是否通过身份验证 |
@group_required() | 检查用户是否属于有权限的用户组访问 |
@anonymous_required() | 检验用户是否已经登录 |
@superuser_only() | 它只允许超级用户才能访问视图 |
@ajax_required | 用于检查请求是否是AJAX请求 |
@timeit | 用于改进某个视图的响应时间,或者只想知道运行需要多长时间 |
05.视图函数和视图类的区别?(高级)
优点 | 缺点 | |
---|---|---|
视图函数 | 容易实现跟理解;流程简单;直接使用装饰器 | 代码难以重用;处理HTTP请求时要有分支表达式 |
视图类 | 易拓展跟代码重用;可以用混合类继承;单独用类方法处理HTTP请求;有许多内置的通用视图函数 | 不容易去理解;代码流程负载;父类混合类中隐藏较多代码;使用装饰器时需要额外的导入或覆盖方法 |
高阶
01.Django如何实现高并发?(高级)
-
Nginx + uWSGI + Django
-
Nginx + gunicorn + gevent + Django
02.如何提高Django应用程序的性能?(高级)
- 前端优化
1.减少 http 请求,减少数据库的访问量,比如使用雪碧图。
2.使用浏览器缓存,将一些常用的 css,js,logo 图标,这些静态资源缓存到本地浏览器,通过设置 http 头中的 cache-control 和 expires 的属性,可设定浏览器缓存,缓存时间可以自定义。
3.对 html,css,javascript 文件进行压缩,减少网络的通信量。
- 后端优化
1.合理的使用缓存技术,对一些常用到的动态数据,比如首页做一个缓存,或者某些常用的数据做个缓存,设置一定得过期时间,这样减少了对数据库的压力,提升网站性能。
2.使用 celery 消息队列,将耗时的操作扔到队列里,让 worker 去监听队列里的任务,实现异步操作,比如发邮件,发短信。
3.就是代码上的一些优化,补充:nginx 部署项目也是项目优化,可以配置合适的配置参数,提升效率,增加并发量。
4.如果太多考虑安全因素,服务器磁盘用固态硬盘读写,远远大于机械硬盘,这个技术现在没有普及,主要是固态硬盘技术上还不是完全成熟, 相信以后会大量普及。
5.服务器横向扩展。
03.Django中当用户登录到A服务器进入登陆状态,下次被nginx代理到B服务器会出现什么影响?(高级)
如果用户在A应用服务器登陆的session数据没有共享到B应用服务器,那么之前的登录状态就没有了。
04.谈谈对Celery的理解(高级)
Celery是由Python开发、简单、灵活、可靠的分布式任务队列,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务。
Celery侧重于实时操作,但对调度支持也很好,其每天可以处理数以百万计的任务。
特点:
简单:熟悉celery的工作流程后,配置使用简单
高可用:当任务执行失败或执行过程中发生连接中断,celery会自动尝试重新执行任务
快速:一个单进程的celery每分钟可处理上百万个任务
灵活:几乎celery的各个组件都可以被扩展及自定制
05.Celery有哪些应用场景?(高级)
-
异步任务:当用户在网站进行某个操作需要很长时间完成时,我们可以将这种操作交给Celery执行,直接返回给用户,等到Celery执行完成以后通知用户,大大提好网站的并发以及用户的体验感。例如:发送验证邮件
-
定时任务:向定时清除沉余数据或批量在几百台机器执行某些命令或者任务,此时Celery可以轻松搞定。
06.Celery的工作原理是什么?(高级)
Celery由以下三部分构成:消息中间件(Broker)、任务执行单元Worker、结果存储(Backend),如下图:
工作原理:
任务模块Task包含异步任务和定时任务。
其中,异步任务通常在业务逻辑中被触发并发往消息队列,而定时任务由Celery Beat进程周期性地将任务发往消息队列;
任务执行单元Worker实时监视消息队列获取队列中的任务执行;
Woker执行完任务后将结果保存在Backend中;
消息中间件Broker
消息中间件Broker官方提供了很多备选方案,支持RabbitMQ、Redis、Amazon SQS、MongoDB、Memcached 等,官方推荐RabbitMQ。
任务执行单元Worker
Worker是任务执行单元,负责从消息队列中取出任务执行,它可以启动一个或者多个,也可以启动在不同的机器节点,这就是其实现分布式的核心。
结果存储Backend
Backend结果存储官方也提供了诸多的存储方式支持:RabbitMQ、 Redis、Memcached,SQLAlchemy, Django ORM、Apache Cassandra、Elasticsearch。