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面试题及总结的更多相关文章

  1. python学习之旅

    python学习分类 python基础    +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...

  2. python面试导航

    python面试题库 python基础 等待更新中 函数 等待更新中 面向对象 等待更新中 高级编程 等待更新中 数据库 等待更新中 前端&django 等待更新中 crm 等待更新中 drf ...

  3. python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)

    考试第二部分:MySQL数据库 6.  MySQL中char和varchar的区别(1分) char是定长,varchar是变长. char的查询速度比varchar要快. 7.   MySQL中va ...

  4. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  5. .NET面试题系列[8] - 泛型

    “可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...

  6. 关于面试题 Array.indexof() 方法的实现及思考

    这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...

  7. 对Thoughtworks的有趣笔试题实践

    记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...

  8. 从阿里巴巴笔试题看Java加载顺序

    一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...

  9. JAVA面试题

    在这里我将收录我面试过程中遇到的一些好玩的面试题目 第一个面试题:ABC问题,有三个线程,工作的内容分别是打印出"A""B""C",需要做的 ...

随机推荐

  1. 不懂APS系统?十个问答让你对APS瞬间明明白白

    本文为您解答APS自动排程系统导入中客户常见的问题,帮助您评估企业是否适合导入APS,并了解需要的人力和资金的投入. Q1:哪些企业需要导入APS? A1: 编制生产计划有困难的企业都可以开始考虑导入 ...

  2. android studio学习----偏好设置

    主要找到设置的界面:Files->Settings , android studio里面没有preferences 1.字体大小设置 进入后你也许发现字体大小或者样式不符合你的习惯,比如我是觉得 ...

  3. The field file exceeds its maximum permitted size of 1048576 bytes.

    问题原因:Spring Boot内置tomcat限制了请求文件的大小 下面是修改方法:根据自己的Spring Boot版本 2.0之后版本的修改方式 在主配置文件 application.proper ...

  4. Shell 编程 免交互 expect

    本篇主要写一些shell脚本免交互expect的使用. 概述 Expect是建立在tcl基础上的一个工具,Expect 是用来进行自动化控制和测试的工具.主要解决shell脚本中不可交互的问题. 安装 ...

  5. OAuth 2.0 的四种授权模式

    RFC 6749 OAuth 2.0 的标准是 RFC 6749 文件.该文件先解释了 OAuth 是什么. OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者.......资源 ...

  6. Linux服务器安全加固

    关于对公司网站服务器安全加固的一些想法及思路: 一.修改密码和ssh登录端口,并且尽可能的用密钥对登录,禁止用密码登录(主要针对Linux)二.修改/etc/hosts.allow 设置仅仅允许某几台 ...

  7. 三块sm865组建RAID0

    介绍 使用三块sm865组件raid0,cpu为6700k,主板为华硕的z170-A 这里使用的是主板自带的raid0,不是win10自带的带区卷 CrystalDiskMark AS SSD Ben ...

  8. P1908 逆序对-(cdq分治)

    https://www.luogu.org/problem/P1908 沿用归并排序的思想求逆序对. 坑1:结果爆int型,需要用longlong 坑2:相对于归并排序,在比较的时候多了一个等号 举例 ...

  9. (HK1-1)海康网络摄像机的使用

    https://blog.csdn.net/u014552102/article/details/86700057 一.手机客户端操作:  首先在莹石商城官网https://www.ys7.com/下 ...

  10. OpenCV 学习笔记(14)为轮廓创建边界旋转框和椭圆

    https://docs.opencv.org/3.4/de/d62/tutorial_bounding_rotated_ellipses.html 不旋转 #include "opencv ...