面试题【HTTP协议详细,Django请求生命周期详细,中间件应用,跨域,ORM操作以及其他】

写博客前,导师给发了一道懵逼的面试题,虽然开发用不到,但是还是知道的好!

    num=55.3
    i=int(num)
    ta=float((num-i)*100)
    tb=int(ta)
    print(ta,tb)       #29.99999999915    29 

这是一个C++的面试题,首先num是55.3,i=int(num),那么i=53,接着ta=55.3-55=0.3,然后乘以100,就是30,tb=30.

感觉按着思路一步步没毛病,可是计算机却不这么想!

运行完发现是29.99999999999716,和29为什么和想象中不一样呢?那么这个问题是因为数字在计算机中是二进制存储的,

小数的存储没有正好二进制对应,所以只是无限接近。

0.3就是0.3000000000000000004,无限接近却不是3。

同样的这个也是这个样子,所以下面的结果也就容易想通了!

 开始笔记

1.HTTP协议

  ----我理解的Http协议就是传输的格式。
  ----请求链接,请求完就断开(无状态,短连接)

 

往下会继续问头里和体里有什么?

 

2.关于web框架

我原来的学习django框架,从socket服务端开始学起。(一定要说)自己创造了一个docket服务器来充当:网站,浏览器当socket客户端更清楚的明白到底http协议是什么?
-请求头 \r\n\r\n 请求体
-响应头 \r\n\r\n 响应体

 

2.常见的请求头:

refer ,host,content-type user-agent[列出来背]上一篇有具体的

 

3.常见的请求体(有可能会问到常见的请求体):

首先要明确的是

    ---GET没有请求体
    ---POST的请求体:

 

不同的方式下:

Form表单提交:
    POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&passwd=123&xxx=xxx...

 

  Ajax请求:
    POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\n{"username":"alex","passwd":"123"}

 

补充:

django获取请求体:
            
            如果前面的ajax发送的get请求:
            $.ajax({
            url: "/check_username_exist/",
            type: "get",
            data: {"username": username},




        
            后端可以通过request.GET.get拿到
            username = request.GET.get("username")



但是如果是POST的ajax请求,不能通过request.POST.get拿到,django的request.POST不支持解析json格式,只支持urlencode.但是rest-framework支持所有格式。
            -request.body(通过body可以拿到原生数据,需要自己解析)
            -request.POST

4.Django请求生命周期:

  首先要知道WSGI是什么?  

  -wsgi:就是socket服务端,用于接受用户请求并将请求进行初次封装,然后将请求交给web框架(django,flask)

  (1)请求进入

    请求进来,wsgi(socket服务端)做一次初步的封装(request)

 

  (2)再到django进行二次封装。(request对象)

    源码中WSGIHandler()里面的__call__方法
    request=self.request_class(environ)

 

解析:environ就是第一次封装

request=self.request_class(environ)第二次封装
[request_class=WSGIRequest]

 

  (3)经过中间件,帮助我们队请求进行校验火灾请求对象中添加其他数据,
        

      如csrf_token,request.session

 



  (4)进入路由匹配

      找到视图函数之后,执行视图函数进行业务逻辑的处理

                      -->可能会涉及到数据库的操作(ORM)

                      -->可能会涉及到模板的渲染(render)



  (5)往回返response的时候通过中间件的process_response方法进行处理.


  (6)然后通过wsgi返回给浏览器(用户)。[其实就是socket的sendall]

讲生命周期,应该把每一步是干什么的说清楚最好!!!

 

 

5.中间件

    ---5个方法


    ---应用场景:

      ----登录认证(由登录验证的装饰器而来,如果视图函数太多,总不能一个个的去加装饰器吧)

    

      ----权限(设置访问白名单)***着重关注(公司对权限都很感兴趣)

 

权限基本实现的流程讲解:

【当用户登录时获取当前用户所有权限放到session中,用户访问需要权限的页面时从session拿到这个用户并且拿到他拥有的权限,
 判断URL在不在这个权限列表中如果在就通过,如果不在就直接在中间件进行返回,告诉他不能进行访问!】

 

6.跨域处理

    jsonp: 巧妙利用scrpit标签进行处理

      缺点:1.双方必须约定好函数,
         2.只能发GET请求。

 

    cors: 设置响应头,告诉浏览器不要拦截。[本地开发前后端分离项目的时候]

      因为VUe的端口和rest-framework不一样,所以需要跨域。
      真正上线后,vue会和后台是同一个域名,不会跨域。

 

7.ORM操作

- only
- defer
- seleted_related
- prefetch_related

 

示例:
class Depart(models.Model): 5个部门
title = models.CharField(...)

class User(models.Model): 10个用户
name = models.CharField(...)
email = models.CharField(...)
dp = models.FK(Depart)

 

1.以前的你:11次单表查询

result = User.objects.all()
for item in result:
print(item.name,item.dp.title)

 

2. seleted_related,主动做连表查询(1次链表)[支持O2O,FK]

result = User.objects.all().seleted_related('dp')
for item in result:
  print(item.name,item.dp.title)

问题:如果链表多,性能越来越差。


3. prefetch_related:2次单表查询 [支持O2O,FK,M2M]

# select * from user ;
# 通过python代码获取:dp_id = [1,2]
# select * from depart where id in dp_id
result = User.objects.all().prefetch_related('dp')
for item in result:
  print(item.name,item.dp.title)

补充:如果数据量比较大,不会使用FK,允许出现数据冗余,硬盘不值钱,用户体验最值钱。

 

8.restful以及相关源码

 

django rest-framework是干什么的?

 

  快速搭建基于restful规范的接口。

 

你理解的restful规范!

  restful是一个规范,规定API如何编写,通过他可以让我们API更加简介可维护。

 

10条基本【必会】

  ---method不同,
  ---https, 
  ---面向资源,
  ---api,
  ---版本号,
  ---条件,
  ---返回值,
  ---状态码,
  ---错误信息,
  ---hymedia,

 

django-rest-framework

 

    -认证:登录(设置Token值)

 

    -频率:

         [取到IP地址,ip为键,时间戳为值],取到最新的访问时间,
          跟列表内的进行对比,把过期的剔除掉,如果新访问的剔
          除不掉以前的表示访问过快,这样返回他不能进行继续访问]

    面试技巧【掌握主动权】:

      

      因为会有代理IP的存在,那么应该用登录用户来做这个,登录用户不能频繁的更换IP。

      匿名用户不好做。(封禁代理IP,代理过多,没招!)

      如果对方让你提一个需求,【匿名用户的话,取到电脑的MAC地址,这个貌似不能作假】

      一般不要说做过这个频率访问的应用,应该是说自己近期看过源码。

    建议

        你可以提一些实现不了的方案,然后说这个好像也坐不了,反抛给他问他或者他们公司怎么去做的,或者有什么更好的方案?

 

      一般情况下都是默认将访问记录放在缓存中,redis,memacached(访问十分的快)

      匿名:
        1.1.1.1 :[时间,时间,时间]

      登录:
        user : [时间,时间,时间]

    

     -权限

        ------

    -序列化:

      1.面向对象。构造方法是__init__,真正的构造方法是__new__【临时补充知识点】

          many=True[ListSerializer对象]
          many=False[就是当前对象]

    序列化根据many的不同进行判断然后去进行实例化。

   

   -列表生成式:

      [permisson() for permission in self.permission_class]
      
      生成一个个的实例化对象

 

posted @ 2018-10-19 19:57  G先生  阅读(30)  评论(0编辑  收藏  举报

:guocheng