drf面试题及总结
drf面试题及总结
1.什么是前后端分离
2.什么是restful规范
3.模拟浏览器进行发送请求的工具
4.查找模板的顺序
5.什么是drf组件
6.drf组件提供的功能
7.drf继承过哪些视图类?以及他们之间的区别?
8.GenericAPIView视图类的作用
9.drf版本的实现过程?
10.drf组件认证的实现过程?
11.drf组件权限的实现过程?
12.drf组件中节流的实现方式?
13.序列化时many=True和many=False的区别?
14.drf各个功能的使用程度,不代表重要程度
15.什么是jwt? 它的优势是什么?
16.装饰器
17.面向对象中基于继承+异常处理来做的约束
18.面向对象封装
19.面向对象继承
20.反射
21.ajax请求写法
22.跨域问题
23.如何解决ajax+跨域?
24.常见的HTTP请求方法
25.http请求中Content-type请求头
26.django中F查询
27.django中获取空Queryset
28.基于django的fbv和cbv都能实现遵循restful规范的接口
1、什么是前后端分离
前端:整个页面显示以及页面的交互逻辑,用ajax和node作为交互。其中node作为中间层
后端:提供api接口,利用redis保存session,与数据库交互
步骤:
1)客户端(浏览器)向node请求页面交互。
2)node向后端(这里用java)转发请求。java在发送请求到数据库。
3)java返回结果给node。node返回页面,提供数据。
node:
node主要是为了分层开发,前端不需要知道后端是怎么提供数据,怎么操作。后端也不需要知道node是怎么操作,前端是怎么部署。前端可以利用node自己作处理。
node本身有着异步,非阻塞I/o。在处理并发量比较大的数据请求上有很大的优势。
2、什么是restful规范
restful规范是一套规则,用于API中之间进行数据交换的约定。
它的具体规则有:
1、https代替http,保证数据传输时的安全
2、在url中一般要体现api标识,这样看到url就知道他是一个api
建议:https://www.zdr.com/api/...(不会存在跨域问题)
3、在接口中要体现版本,可放在url中也可以放在请求头中
建议:https://www.zdr.com/api/v1/...
4、restful也称为面向资源编程,视网络上的一切都是资源,对资源可以进行操作,所以一般资源都用名词
5、如果要加入一些筛选条件,可以添加在url中
https://www.zdr.com/api/v1/user/?page=1&type=9
6、根据method请求方法不同做不同操作
get/post/put/patch/delete
7、根据请求方法不同返回不同的值
get全部/post返回添加的值/put/patch/delete不返回值
8、给用户返回状态码
- 200——成功
- 300——301是永久重定向,302是临时重定向
- 400——403拒绝中间件的csrftoken认证 /404找不到
- 500——服务端代码错误
9、操作异常时,要返回错误信息
{
error: "Invalid API key"
}
10、对于下一个请求要返回一些接口: Hypermedia AP
{
'id':2,
'name':'alex',
'age':19,
'depart': "http://www.luffycity.com/api/user/30/"
}
3、模拟浏览器进行发送请求的工具
postman
4、查找模板的顺序
优先查找根目录下:templates
根据app的注册顺序去每个app的templates目录中找
5、什么是drf组件
drf的全称是Django RESTful Framework
它是一个基于django开发的组件,本质是一个django的app
drf可以帮我们快速开发出一个遵循restful规范的程序
6、drf组件提供的功能
免除csrf认证
视图(三种:(1)APIView,(2)ListAPIview,(3)ListModelMixin)
版本处理
认证
权限
节流(频率限制)
解析器
筛选器
分页
序列化和数据校验:可以对QuerySet进行序列化,也可以对用户提交的数据进行校验——展示特殊的数据
depth
source:无需加括号,在源码内部会去判断是否可执行,如果可执行自动加括号。【多对一、一对一/choice】
SerializerMethodField定义钩子方法【多对多】
渲染器:可以帮我们把json数据渲染到drf自己的页面上。
7、drf继承过哪些视图类?以及他们之间的区别?
第一种:APIView
第一种遵循了CBV的模式,里面的功能比较多但是需要自己写的代码也有很多
提供了免除csrf认证,版本处理、认证、权限、节流、解析器、筛选器、分页、序列化、渲染器
第二种:ListAPIView,RetrieveAPIView,CreateAPIView,UpdateAPIView,DestroyAPIView
第二种则在第一种的基础上,封装了许多我们需要自己的写的代码,许多功能的实现只需要给专属的变量名赋值就可以实现该功能
第三种:GenericViewSet、ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin
第三种则重构了APIView中的as_view()方法,结合请求方法和不同Mixin类的方法名从而进行执行不同的功能。与前面两种最主要的区别是url路由中as_view()方法中需要传值。
目前使用的主要目的是把第二种的bug(查询全部数据的功能和查询单个数据的功能无法在一个类中实现)实现在一个类中!
8、GenericAPIView视图类的作用
总结:GenericAPIView主要为drf内部帮助我们提供增删改查的类LIstAPIView、CreateAPIView、UpdateAPIView、提供了执行流程和功能,
我们在使用drf内置类做增删改查时,就可以通过自定义 静态字段(类变量)或重写方法(get_queryset、get_serializer_class)来进行更高级的定制。
他提供了一些规则,例如:
class GenericAPIView(APIView):
serializer_class = None
queryset = None
lookup_field = 'pk' filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self):
return self.queryset def get_serializer_class(self):
return self.serializer_class def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset @property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator 他相当于提供了一些规则,建议子类中使用固定的方式获取数据,例如:
class ArticleView(GenericAPIView):
queryset = models.User.objects.all() def get(self,request,*args,**kwargs):
query = self.get_queryset()
我们可以自己继承GenericAPIView来实现具体操作,但是一般不会,因为更加麻烦。
而GenericAPIView主要是提供给drf内部的 ListAPIView、Create....
class ListModelMixin:
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) class ListAPIView(mixins.ListModelMixin,GenericAPIView):
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class MyView(ListAPIView):
queryset = xxxx
ser...
9、drf版本的实现过程?
# drf自带的版本类
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
# 允许出现的版本
"ALLOWED_VERSIONS": ['v1', 'v2'],
# 如果没有传版本,可以使用默认版本
default_version = api_settings.DEFAULT_VERSION
# 设置url中获取版本的变量,默认是version
version_param = api_settings.VERSION_PARAM 当前端来请求时,执行了as_views()方法,如果设置了全局版本或者进入了设置了版本的功能函数,则会先执行APIView类中的dispatch方法,之后再执行initial方法,然后进入了self.determine_version方法,
里面会先判断是否有versioning_class,如果没有就返回(None,None),就代表没有版本,如果有就执行versioning_class(URLPathVersioning)类中的determine_version方法,它会返回版本,里面会判断,
如果获取到的version为空则返回默认版本,并且还要判断版本是否存在允许出现的版本列表中,返回版本之后,再把版本号和版本类分别赋值给request.version和request.versioning_scheme
10、drf组件认证的实现过程?
当用户进行登录的时候,运行了登录类的as_view()方法,
1、进入了APIView类的dispatch方法
2、执行了self.initialize_request这个方法,是重定义request,并且得到了自己定义的认证类对象
3、执行self.initial方法中的self.perform_authentication,里面运行了user方法
4、再执行了user方法里面的self._authenticate()方法
5、然后执行了自己定义的类中的authenticate方法,自己定义的类继承了BaseAuthentication类,里面有 authenticate方法,如果自己定义的类中没有authenticate方法会报错。
6、把从authenticate方法得到的user和auth赋值给user和auth方法
7、这两个方法把user和auth的值赋值给了request.user:是登录用户的对象,request.auth:是认证的信息字典





11、drf组件权限的实现过程?
当用户执行一个业务的时候,运行了as_view方法
1、进入了APIView类的dispatch方法
2、进入self.initial方法中的self.check_permissions(request)方法
3、里面执行了for循环,把每个权限类实例化对象,
4、执行自己定义的权限类里面的has_permission方法,里面会判断request.user是否存在
5、不存在就返回False,存在就返回True
6、之后执行self.permission_denied报错方法,返回的是False就报错,可以自定义报错信息,在has_permission方法中写message = {"status": False, "error": "登录成功之后才能评论"},
就实现了自定义报错
7、如果返回的是True就让他进入功能



12、drf组件中节流的实现方式?
匿名用户通过ip地址来控制访问频率,已登录用户通过id来控制
首先要设置配置文件:
# 也可以设置全局,
"DEFAULT_THROTTLE_CLASSES":["rest_framework.throttling.AnonRateThrottle",]
# 设置访问频率——一分钟10次
"DEFAULT_THROTTLE_RATES": {
"anon":"10/m"
}
- 实现原理
把所有登录记录时间放在一个列表中,当用户请求网页的时候,用现在的时间减去约束的时间间隔,然后把小于这个时间记录排除,再计算出时间间隙的记录条数,
如果其中的条数小于规定的条数则可以访问并且把当前时间添加进列表中,如果大于或等于则不让其访问。
- 具体流程
当用户请求网页的时候,后台允许该界面的url中的as_views(),运行源码的APIView中的dispatch方法,运行initial方法,里面的check_throttles方法,
循环运行节流类中的allow_request方法,但是AnonRateThrottle等类中没有,去执行SimpleRateThrottle类中的allow_request方法,里面就是实现原理中的代码,
如果可以访问返回True,如果不让访问则返回False,之后返回check_throttles,如果是False则运行SimpleRateThrottle类中的wait方法得到需要等待的时间在页面上显示!


13、序列化时many=True和many=False的区别?
在使用APIView时,数据展示的时候序列化多个数据的时候用many=True,序列化单个数据的时候用many=False
案例:
category_all = models.Category.objects.all()
ser_category = serializer.HomeCategorySerializer(instance=category_all, many=True)
article_obj = models.Article.objects.filter(id=pk).first()
ser = serializer.OneArticleSerializer(instance=article_obj, many=False)
14、drf各个功能的使用程度,不代表重要程度
*****
解析器:request.query_parmas/request.data
视图
序列化
渲染器:Response
****
request对象封装
版本处理
分页处理
***
认证
权限
节流
15、什么是jwt? 它的优势是什么?
jwt的全称是json web token, 一般用于用户认证
jwt的实现原理:
- 用户登录成功之后,会给前端返回一段token。
- token是由.分割的三段组成。
- 第一段header:类型+算法+base64url加密
- 第二段paylod:用户信息+超时时间+base64url加密
- 第三段sign:hs256(前两段拼接)加密 + base64url
- 以后前端再次发来信息时
- 超时验证
- token合法性校验
优势:
- token只在前端保存,后端只负责校验。
- 内部集成了超时时间,后端可以根据时间进行校验是否超时。
- 由于内部存在hash256加密,所以用户不可以修改token,只要一修改就认证失败。
16、装饰器
应用区域:
- 在django中csrftoken认证中使用了
- 在flask中的路由url中也使用了
标准装饰器:
def outer(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
@outer
def index(a1):
pass
index()
17、面向对象中基于继承+异常处理来做的约束
在drf的版本、认证、权限、节流的源码中都大量使用了面向对象中的继承和异常处理
class BaseVersioning:
def determine_version(self, request, *args, **kwargs):
raise NotImplementedError("must be implemented") class URLPathVersioning(BaseVersioning):
def determine_version(self, request, *args, **kwargs):
version = kwargs.get(self.version_param, self.default_version)
if version is None:
version = self.default_version
if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
18、面向对象封装
drf源码中的APIView的dispatch中有个self.initialize_request,它返回了一个Request类,它封装了django的request和认证对象列表等其他参数
事例:
class APIView(View):
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
... def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), # [MyAuthentication(),]
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
19、面向对象继承
django中源码大量使用了面向对象的继承
尤其是drf中的继承关系最为明显
事例:
class View(object):
pass
class APIView(View):
def dispatch(self):
method = getattr(self,'get')
method()
class GenericAPIView(APIView):
serilizer_class = None def get_seriliser_class(self):
return self.serilizer_class
class ListModelMixin(object):
def get(self):
ser_class = self.get_seriliser_class()
print(ser_class)
class ListAPIView(ListModelMixin,GenericAPIView):
pass
class UserInfoView(ListAPIView):
pass
view = UserInfoView()
view.dispatch()
20、反射
应用场景:
1、django中的View类的dispatch通过接收到的请求方法变为小写从而使用反射得到类中的相对应方法,比如get方法。
class View(object):
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
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
return handler(request, *args, **kwargs)
2、django中的settings配置文件的源码也使用了反射,并且结合了
import importlib
self.SETTINGS_MODULE = settings_module # 获取到settings文件的路径
mod = importlib.import_module(self.SETTINGS_MODULE) # 通过importlib.import_module获取到settings文件对象
for setting in dir(mod): # 循环获取到settings文件对象里面的属性
if setting.isupper(): # 得到大写的属性名
setting_value = getattr(mod, setting) # 得到属性值比如中间件等其他配置属性
21、ajax请求写法
可模拟任何请求方式向后端发送请求
$.ajax({
url:'地址',
type:'GET',
data:{...},
success:function(arg){
console.log(arg);
}
})
22、跨域问题
浏览器具有”同源策略的限制“,导致 发送ajax请求 + 跨域 存在无法获取数据,只有ajax才能导致跨域,html中的src不会,导致跨域的原因有域名不同或者不同端口、http与https互相发送
简单请求,发送一次请求
复杂请求,先options请求做预检,然后再发送真正的请求
23、如何解决ajax+跨域?
CORS(跨域资源共享):是一种使用额外的 HTTP 头部来允许浏览器可以在一个不同域的网站内获取另一个域下的服务器资源的机制。
本质是设置响应头。
24、常见的HTTP请求方法
get:让后端传给前端想要的数据
post:前端传数据给后端让其添加记录
put:前端传数据和筛选数据的依据给后端让其更新记录
patch:前端传局部数据和筛选数据的依据给后端让其更新局部记录
delete:前端传筛选数据的依据给后端让其删除记录
options:是跨域问题中的复杂请求预检的请求
25、http请求中Content-type请求头
情况一:
content-type:x-www-form-urlencode
name=alex&age=19&xx=10
request.POST和request.body中均有值 情况二:
content-type:application/json
{"name":"Alex","Age":19}
request.POST没值
request.body有值
26、django中F查询
F可以提取某个字段的值,可以用来比较两个字段值的判断,可以更新某个字段的值
Q用来表示条件,使用Q对象来组成各种关系的条件,|=or
27、django中获取空Queryset
models.User.object.all().none()
28、基于django的fbv和cbv都能实现遵循restful规范的接口
FBV:
def user(request):
if request.method == "GET":
pass
CBV:
class UserView(View):
def get():
pass def post():
pass
FBV和CBV的区别:
FBV顾名思义就是函数处理请求,代码冗余比较多,不是面向对象编程
CBV则是使用类中的不同方法来处理请求,迎合了python所推崇的面向对象编程思想。
相比FBV的优点:
1、提高了代码的复用性,可以使用面向对象的计算,比如Mixin(多继承)
2、可以用不同的函数针对不同的http请求方法处理,而不是通过过多的if判断,提高了代码的可读性
drf面试题及总结的更多相关文章
- python学习之旅
python学习分类 python基础 +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...
- python面试导航
python面试题库 python基础 等待更新中 函数 等待更新中 面向对象 等待更新中 高级编程 等待更新中 数据库 等待更新中 前端&django 等待更新中 crm 等待更新中 drf ...
- python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)
考试第二部分:MySQL数据库 6. MySQL中char和varchar的区别(1分) char是定长,varchar是变长. char的查询速度比varchar要快. 7. MySQL中va ...
- python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- .NET面试题系列[8] - 泛型
“可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...
- 关于面试题 Array.indexof() 方法的实现及思考
这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...
- 对Thoughtworks的有趣笔试题实践
记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...
- 从阿里巴巴笔试题看Java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- JAVA面试题
在这里我将收录我面试过程中遇到的一些好玩的面试题目 第一个面试题:ABC问题,有三个线程,工作的内容分别是打印出"A""B""C",需要做的 ...
随机推荐
- 操作mysql数据库的一些命名
一.打开数据库 1.1.打开命令行输入:mysql -u root -p 1.2.root是本地数据库的用户名,然后输入数据库的密码进入. 二.数据库操作 2.1.创建一个数据库:create dat ...
- .NET Core 下调用WebAPI
前言 今天我们介绍多种客户端调用WebApi的方式,可以是原生写的,也可以借助.NET 框架下的其他HTTP库.我们一起来看看它们之间的一些异同吧- RestSharp 首先要介绍的就是这款REST ...
- Linux搭建邮件服务器Postfix+Dovecot+MySQL+PHP
用于搭建的服务器信息 阿里云 Centos 6.5 32位 安装过程1.安装Postfix 版本(2:2.6.6-8.el6) yum -y install postfix 安装完成还需要替换系统自带 ...
- svn忽略target文件
背景:最近项目转移到svn上 发现:项目从svn拉取下来到eclipse中,发现有大量的文件改动,一看都是一些.project之类的配置文件或者是target文件夹,或者下面的文件 这些东西肯定是不需 ...
- Window 2003 IIS + MySQL + PHP + Zend 环境配置
图文详解 下载 Windows 2003 Zend, PHP, PHPMyadmin 与 MySQL Windows 2003 安装包中包含了 Zend,PHP 5.2.17,PHPWind8.7 和 ...
- Game Engine Architecture 12
[Game Engine Architecture 12] 1.the field of physics is vast, and what most of today’s game engines ...
- tf.gather_nd()
tf.gather_nd( params, indices, name=None, batch_dims=0) TensorFlow链接:https://tensorflow.google.cn/ap ...
- TL-WDN5200H无线usb网卡在Linux上的使用
买了个TL-WDN5200H无线usb网卡,但是发现它居然不支持Linux,但是我有时需要在Linux上使用,这就尴尬了.于是到网上搜索资料,终于解决了这个问题. 首先编译安装:https://git ...
- django模板中的extends和include使用方法
一.extends使用方法 首先extends也就是继承,子类继承父类的一些特性.在django模板中通过继承可以减少重复代码. 首先我们建立一个app,名字叫做hello.别忘了在settings. ...
- 调试CEF3程序的方法
CEF3多进程模式调试时按F5只会启动调试Browser进程,要调试Renderer进程就要让进程在启动时就暂停并附加进程. 所幸google早就想到了这一点,chrome的命令行参数就可以办到, - ...







