关于Django+Framework的最完整面试题(2)

文章目录

  • 一、框架对比
    • 1.Django、Flask、Tornado框架对比
    • 2. WSGI / uwsgi/ uWSGI区分
  • 二、Django框架
    • 3.介绍一下FBV和CBV
    • 4.如何给CBV的程序添加装饰器?
    • 5.将自带的sqllite数据库转为MySQL的步骤
    • 6.介绍Model中的ForeignKey字段中的on_delete参数
    • 7.F和Q对象的作用
    • 8.values和values_list的区别?
    • 9.django中间件是什么?用中间件做过什么?
    • 10.django请求的生命周期?
    • 11.django中间件的5个方法?
    • 12.django中间件的应用场景?
  • 三、Django-Framework框架
    • 13.介绍一下restful规范
    • 14.为什么要使用framework框架?
    • 15.framework框架提供的组件
    • 16.介绍一下视图类的继承关系
    • 17.framework如何实现的用户访问频率控制?
  • 四、ORM框架
    • 18.ORM中执行原生sql代码方法
    • 19.列举django orm 中所有的方法
    • 20.使用orm和原生sql的优缺点?
  • 五、其他
    • 21.Django内置组件
    • 22.CSRF实现机制
    • 23.ajax发送post,怎么携带csrftoken?
    • 24.缓存设置
    • 25.django路由系统中name的作用?
    • 26.Http和Https的区别?

一、框架对比

1.Django、Flask、Tornado框架对比

  • Django:简单的说Django是一个大而全的Web框架,内置了很多组件,ORM、admin、Form、 ModelForm、中间件、信号和缓存等。给开发者提高了超高的开发效率。
  • Flask:微型的小而精的Web框架,可扩展性强,内置的组件很少,需要引入第三方组件实现功能业务,如果开发简单的项目,使用Flask比较快速和方便。如果开发大型项目,需要引入大量的第三方组件,这时Flask会越 来越像Django框架。基于wsgi协议部署,使用werkzeug模块实现此协议,模板系统由 Jinja2提供。
  • Tornado:是一个轻量级的Web框架,少而精,性能优越,最出名的就是强大的异步非阻塞和内置WebSocket功能。

2. WSGI / uwsgi/ uWSGI区分

  • WSGI: WSGI的全称是Web Server Gateway Interface(Web服务器网关接口),它不是服务器、python模块、框架、API或者任何软件,只是一种描述web服务器(如nginx,uWSGI等服务器)如何与web应用程序(如用Django、Flask框架写的程序)通信的规范。
    server和application的规范在PEP3333中有具体描述,要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle, Flask, Django。
  • uWSGI :uWSGI是一个全功能的HTTP服务器,实现了WSGI协议、uwsgi协议、http协议等。它要做的就是把HTTP协议转化成语言支持的网络协议。比如把HTTP协议转化成WSGI协议,让Python可以直接使用。
  • uwsgi:与WSGI一样,是uWSGI服务器的独占通信协议,用于定义传输信息的类型(type of information)。每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi【FCGI:fast common gateway interface 快速通用网关接口协议的10倍快。

二、Django框架

3.介绍一下FBV和CBV

  • FBV(function base views) 就是在视图里使用函数处理请求。
  • CBV(class base views) 就是在视图里使用类处理请求。

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django加入了类视图。这样做的优点主要下面两种:
(1)提高了代码的复用性,可以使用面向对象的技术,例如多继承在APIView和listview里体现
(2)可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

4.如何给CBV的程序添加装饰器?

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
 
#引入method_decorator模块
# 1.直接在类上加装饰器
@method_decorator(test,name='dispatch')
class Loginview(View):
    pass
    # 2.直接在处理的函数前加装饰器
    @method_decorator(test)
    def post(self,request,*args,**kwargs):
        pass

5.将自带的sqllite数据库转为MySQL的步骤

第一步:settings.py配置
	DATABASES = {
    	'default': {
        	'ENGINE': 'django.db.backends.mysql',
        	'NAME':'orm',   # 要连接的数据库,连接前需要创建好
        	'USER':'root',  # 连接数据库的用户名
        	'PASSWORD':'1234',  # 连接数据库的密码
        	'HOST':'127.0.0.1',     # 连接主机,默认本级
        	'PORT': 3306,     #  端口 默认3306
    	}
	}

第二步:django默认你导入的驱动是MySQLdb需要换为PyMySQL 
# 在/ORM/ORM/__init__.py里面写入:
	import pymysql
	pymysql.install_as_MySQLdb()

第三步:数据迁移
	python3 manage.py makemigrations
	python3 manage.py migrate

6.介绍Model中的ForeignKey字段中的on_delete参数

django2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常。

7.F和Q对象的作用

  • F对象可以对同一个表的两个字段进行比较
  • Q对象可以构造复杂的查询条件,有与或和取反三种操作,当然我们使用filter方法添加多个条件,默认也是and操作。

8.values和values_list的区别?

  • values : 取字典的queryset
  • values_list : 取元组的queryset
# values 结果为字典型
books = Book.objects.filter(id__lt=6).values('number')
[{'number': '1'}, {'number': '2'}, {'number': '3'}, {'number': '4'}, {'number': '5'}]
 
# values_list 结果为元组型
books = Book.objects.values_list('number')
[('1',), ('2',), ('3',), ('4',), ('5',)]
 
# value_list中flat参数:默认为False,返回时为元组,当为True时,返回为列表。
books = Book.objects.values_list('number', flat=True)
books = ['1', '2', '3', '4', '5']python

9.django中间件是什么?用中间件做过什么?

中间件本质是类,帮助我们在视图函数执行之前,订制一些操作。内置的一些中间件可以做csrf、session等。
我们利用中间件常用来做登录认证、权限、cors(跨域)等。

10.django请求的生命周期?

一个 HTTP 请求,首先被转化成一个 HttpRequest 对象,然后该对象被传递给Request 中间件处理,如果该中间件返回了 Response,则直接传递给 Response 中间件做收尾处理。否则的话 Request 中间件将访问 URL 配置,确定哪个 view 来处理,在确定了哪个 view 要执行,但是还没有执行该 view 的时候,系统会把 request 传递给 view 中间件处理器进行处理,如果该中间件返回了 Response,那么该 Response 直接被传递给 Response 中间件进行后续处理,否则将执行确定的 view 函数处理并返回 Response,在这个过程中如果引发了异常并抛出,会被 Exception 中间件处理器进行处理。

11.django中间件的5个方法?

process_request(self,request)  请求进来,还没有进行路由匹配前
process_view(self, request, view_func, view_args, view_kwargs) 路由匹配之后,能够得到视图函数
process_template_response(self,request,response)   模板渲染时执行
process_exception(self, request, exception)   异常时执行
process_response(self, request, response)     请求有响应时执行

12.django中间件的应用场景?

简单的来说中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,例如:

  • 1.Django项目中默认启用了csrf保护,每次请求时通过CSRF中间件检查请求中是否有正确#token值
  • 2.当用户在页面上发送请求时,通过自定义的认证中间件,判断用户是否已经登陆,未登陆就去登陆。
  • 3.当有用户请求过来时,判断用户是否在白名单或者在黑名单里

三、Django-Framework框架

13.介绍一下restful规范

1.定义: restful API 是一种符合rest风格的接口,rest是一种架构风格,采用http协议。

2.作用:

  • 前后端分离一般会使用restful接口
  • 可以使前后端解耦,减少服务器压力,前后端分工明确,提高安全性

3.主要原则:

  • ①网络上的事务的都被抽象为资源
  • ②每个资源都有唯一的标识符,并且对资源的各自操作不会改变标识符
  • ③所有操作都是无状态的
  • ④同一个资源具有多种表现形式(xml/json等),数据传输一般使用的格式是json(全是双引号),以前用的是webservice,数据传输格式是xml

4.restful API的一些建议

①建议使用https代替http,保证传输数据的安全
②url中要体现api标识
③url中要体现版本
④api接口一般使用名字不使用动词
⑤使用不同的方法来进行不同的操作
⑥给用户返回一些状态码
⑦不同的请求方法返回不同类型的返回值,添加和更新一般返回添加的数据,删除不返回数据,获取数据一般返回列表套字典的形式
⑧操作异常返回错误信息
⑨推荐在返回数据的时候,返回其他相关联的一些数据的接口网址,例如分页器可以返回上一页下一页的网址

5.建议的具体示例

#1、可以根据Http不同的method,进行不同的资源操作
  (5种方法:GET/POST/PUT/DELETE/PATCH)  
#2、restful 提倡面向资源编程,在url接口中尽量要使用名词,不要使用动词
    http://www.luffycity.com/salary  
#3、在url中体现版本号
    https://v1.bootcss.com/mycss
    https://v3.bootcss.com/
    http://www.luffycity.com/v1/salary
    不同的版本可以有不同的接口,使其更加简洁,清晰  
#4、url中体现是否是API接口 
    https://www.bootcss.com/api/mycss    
    http://www.luffycity.com/api/v2/salary
    http://api.luffycity.com/v1/salary
    api可以写在前面也可以写在后面,更推荐写在后面,写在前面可能导致跨域问题。
#5、在url接口中推荐使用Https协议,让网络接口更加安全
    https://www.bootcss.com/v1/mycss?page=3
    https://www.luffycity.com/api/v2/salary
    (Https是Http的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL(安全套接层协议)#6、响应式应该设置状态码
    200系列:成功
    300系列:重定向  301临时重定向  302永久重定向
    400系列:错误
    500系列:代码错误
    返回方式:return HttpResponse('asdadw',status=300)
#7、url中可以添加条件去筛选匹配
    https://www.bootcss.com/v1/mycss?page=3
    https://www.luffycity.com/api/v2/salary?page=1&size=10
#8、根据返回值不同做不同的操作
    https://www.luffycity.com/api/v2/salary
        GET:返回所有的列表
            {
                code:10000,
                data:[
                    {'id':1, 'title':'高亮'},
                    {'id':2, 'title':'小东北'}
                ]
            }
        POST:返回新增的数据
            {'id':3, 'title':'龙泰'}
    https://www.luffycity.com/api/v2/salary/1/
        GET:获取单条数据 {'id':1, 'title':'高亮'}
        PUT:更新   {'id':1, 'title':'高亮'}
        PATCH:局部更新  {'id':1, 'title':'高亮'}
        DELETE:删除
#9、返回错误信息(错误信息可以是一个字典)
    {
        code:100001,
        error:'xxx错误'
    }
    
#10、RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么
  如果遇到需要跳转的情况 携带调转接口的URL
      ret = {
            code: 1000,
            data:{
                id:1,
                name:'小强',
                depart_id:https://www.luffycity.com/api/v1/depart/8/
            }
        }

14.为什么要使用framework框架?

  • 不是必须要使用,只不过使用了视图类可以更加的规范,让我们前后端降低耦合性,更加安全快捷。
  • 增删改查的实现流程基本一样,使用视图类可以更快捷的开发。
  • 在序列化的时候,操作数据不同,但是流程相似,可以继承 serializers.ModelSerializer类简写

15.framework框架提供的组件

  • 1.序列化组件:serializers ,对queryset序列化以及对请求数据格式校验
  • 2.视图组件, 帮助开发者提供了一些类,并在类中提供了多个方法
  • 3.渲染器 定义数据如何渲染到到页面上,在渲染器类中注册(renderer_classes)
  • 4.解析器 选择对数据解析的类,在解析器类中注册(parser_classes)
  • 5.分页 对获取到的数据进行分页处理, pagination_class
  • 6.路由组件routers 进行路由分发
  • 7.认证组件 写一个类并注册到认证类(authentication_classes),在类的的authticate方法中编写认证逻
  • 8.权限组件 写一个类并注册到权限类(permission_classes),在类的的has_permission方法中编写认证逻辑
  • 9.频率限制 写一个类并注册到频率类(throttle_classes),在类的的allow_request/wait 方法中编写认证逻辑
  • 10.版本 版本控制用来在不同的客户端使用不同的行为

16.介绍一下视图类的继承关系

class View(object):

class APIView(View): 
    # 封装了view,并且重新封装了request,初始化了各种组件

class GenericAPIView(views.APIView):
    # 增加了一些属性和方法,如get_queryset,get_serializer

class GenericViewSet(ViewSetMixin, generics.GenericAPIView)
    # 父类ViewSetMixin 重写了as_view,返回return csrf_exempt(view)
    # 并重新设置请求方式与执行函数的关系
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
   # 继承了mixins下的一些类,封装了list,create,update等方法,还继承了GenericViewSet

17.framework如何实现的用户访问频率控制?

方法: 使用IP/用户账号作为键,每次的访问时间戳作为值,构造一个字典形式的数据,存起来,每次访问时对时间戳列表的元素进行判断,把超时的删掉,再计算列表剩余的元素数就能做到频率限制了。

特殊:

  • 匿名用户:使用IP控制,但是无法完全控制,因为用户可以换代理IP
  • 登录用户:使用账号控制,但是如果有很多账号,也无法限制

四、ORM框架

18.ORM中执行原生sql代码方法

django中的ORM提供的操作功能有限,在模型提供的查询API不能满足实际工作需要时,可以在ORM中直接执行原生sql语句。Django 提供两种方法使用原生SQL进行查询:一种是使用raw()方法,进行原生SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。

1.raw()方法执行原生sql语句:(调用的类名不区分是谁,只要存在均可执行)
  ret=models.Book.objects.raw('select * from app01_book')
  for book in ret:
      print(book.book_name)

2.直接执行自定义原生sql语句(完全避开模型层,类似pymysql操作)
	from django.db import connection
	cursor=connection.cursor()
	cursor.execute('select * from app01_book')
	ret=cursor.fetchall()
	print(ret)

19.列举django orm 中所有的方法

方法 解释
all() 查询所有结果
filter(**kwargs) 它包含了与所给筛选条件相匹配的对象
get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个, 如果符合筛选条件的对象超过一个或者没有都会抛出错误。
exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
order_by(*field): 对查询结果排序
reverse() 对查询结果反向排序
count(): 返回数据库中匹配查询(QuerySet)的对象数量。
first(): 返回第一条记录
last(): 返回最后一条记录
exists(): 如果QuerySet包含数据,就返回True,否则返回False
values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
values_list(*field) 它与values()非常相似,返回的是一个元组序列,values返回的是一个字典序列
distinct(): 从返回结果中剔除重复纪录
delete(): 立即删除对象而不返回任何值,delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。
update(): 对于任何结果集(QuerySet)均有效,这意味着可以同时更新多条记录。 update()方法会返回一个整型数值,表示受影响的记录条数。

20.使用orm和原生sql的优缺点?

ORM优点:

  • ORM是一个操作数据库的框架
  • ORM会将python代码翻译成对应数据库的sql语句
  • ORM会将数据库中的表,映射成python中的类
  • 提高开发效率,降低开发成本
  • 可以很方便地引入数据缓存之类的附加功能
  • 可以降低数据库和程序之间的耦合,专注业务代码

ORM缺点:

  • 自动化进行关系数据库的映射需要消耗系统性能
  • ORM生成的sql语句,不是最优的sql语句,执行效率会比较低。

sql优点

  • 执行速度快、性能强。

sql缺点:

  • 开发速度慢

五、其他

21.Django内置组件

  • admin组件:后台数据管理工具
  • forms组件:生成html标签和后台校验
  • paginator组件:分页器
  • auth组件:用户认证组件,用session记录登录验证状态

22.CSRF实现机制

Django 原生支持一个简单易用的跨站请求伪造的防护。当提交一个启用CSRF 防护的POST 表单时,你必须使用上面例子中的csrf_token 模板标签。

  • 第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端把这个token放到cookie中交给前端页面;
  • 第二步:下次前端需要发起请求(比如发帖)的时候把这个token值加入到请求数据或者头信息中,一起传给后端;Cookies:{csrftoken:xxxxx}
  • 第三步:后端校验前端请求带过来的token和SESSION里的token是否一致;

23.ajax发送post,怎么携带csrftoken?

方式1:后端将csrftoken传到前端,发送post请求时携带这个值发送
$.ajaxSetup({
    data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

方式2:获取form中隐藏标签的csrftoken值,加入到请求数据中传给后端:
data: {
    csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val()
},

方式3:cookie中存在csrftoken,将csrftoken值放到请求头中
<script src="{% static 'js/jquery.cookie.js' %}">script>
$.ajax({ 
    headers:{"X-CSRFToken":$.cookie('csrftoken')},
})

24.缓存设置

Django 的缓存配置是通过 setting 文件的 CACHES 配置来实现的。以数据库缓存为例:

第一步:使用数据库缓存前,要在 settings.py 添加如下设置:
CACHES = {
    'default': {
        # 使用数据库缓存
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        # 用于保存缓存数据的表的名字
        'LOCATION': 'my_cache_table',
    }
}

第二步:然后运行这个命令来创建缓存表:
python manage.py createcachetable

25.django路由系统中name的作用?

urlpatterns = [   
	url(正则表达式, views视图函数,参数,别名), 
]
name:
对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取了个全局变量名,你只需要修改这个全局变量的值,在整个Django中引用它的地方也将同样获得改变。

26.Http和Https的区别?

  • 首先Https是Http的安全版,即HTTP下加入SSL层就是Https;
  • 默认端口号不同,Http是80端口,Https是443端口;
  • Http是超文本传输协议,信息是明文传输,可以自定义证书,在服务端创建一对证书,在客户 端必须携带证书;
  • 采用https 的server 必须从CA 申请一个用于证明服务器用途类型的证书. 该证书只有用于对应的server 的时候,客户才信任此主机.

你可能感兴趣的:(面试题)