面试整理:Web框架

前端基础

1、基础中的基础

HTML

CSS

JS

 2、框架和类库

Jquery

BootStrap

Vue.js

3、响应式布局的本质

也即自适应各种平台,例如电脑端显示应有的样式、移动端显示应有的样式;

浏览器窗口大小变化时,显示该大小应有的样式。

BootStrap的本质(源码),都是通过各种 CSS 样式实现的。

4、简单实现响应式布局

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>响应式布局本质</title>
    <!--简单实现响应式布局-->
    <style>
        body{
            margin: 0;
        }
        .pg-header{
            background-color: red;
            height: 50px;
        }

        /*浏览器窗口宽度大于768,背景色变为 green*/
        @media (min-width: 768px) {
            .pg-header{
                background-color: green;
            }
        }

        /*浏览器窗口宽度大于992,背景色变为 pink*/
        @media (min-width: 992px) {
            .pg-header{
                background-color: pink;
            }
        }
    </style>
</head>
<body>


<div class="pg-header"></div>

</body>
</html>
响应式布局实现

5、JqueryAjax和原生Ajax

Jquery Ajax: $.ajax(......)

原生Ajax: XMLHttpRequest 

6、跨域

JSONP

CORS

  - 简单请求

  - 复杂请求 

PS:

  参见:http://www.cnblogs.com/bigtreei/p/8921265.html#_labelTop

Flask框架

7_0、Flask请求生命周期?

 

7_1、Flask的优势?

 

7_2、Flask内置功能的依赖关系?

 

7_3、写一个Flask服务

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

8、Flask内置功能

# 配置 config
app = Flask(__name__)
app.config['DEBUG'] = True
# 路由 route
# 视图 
# 模板  template
# Session 
内置session 需要配置secret_key, 存放于cookie
# 消息闪现 flash
# 蓝图  blueprint
# 装饰器
# 中间件 middleware

9、Flask中使用装饰器

from functools import wraps
#检查是否登录
def checkLogin(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not flask.session.has_key('userid') or flask.session['userid'] == 0:
            return redirect('/login', code=302)
        return f(*args, **kwargs)
    return decorated_function

@app.route('/', methods=['GET'])
@checkLogin
def index():
    return "user is login"

@app.route('/my', methods=['GET'])
@checkLogin
def index():
    return "user center"

10、Flask中两个特殊装饰器

@app.before_request

 

@app.after_request

 

11、Flask中常用的第三方组件

# Flask组件
flask-session  session放在redis
flask-SQLAlchemy
flask-migrate 
flask-script 
blinker

# 第三方组件
wtforms
dbutile
gevnet-websocket

# 自定义Flask组件
auth 
参考flask-login组件

12_1、threading.local 以及作用?

 

12_2、Flask上下文管理流程以及和django比较?

 

12_3、Flask中上下文管理主要涉及到了那些相关的类?并描述类主要作用?

 

12_3、为什么要把Local的值维护成一个列表?

 

12_4、Flask中多app应用是怎么完成?

 

12_5、Flask中g的作用?

# 可以简单啊理解为针对与一次请求的全局变量集合

13、Flask主要用到了哪些技术

# 反射
# 面向对象:下划线方法
# 线程相关 threading.local.

14、实现一个栈&栈有哪些特性?

class Stack(object):
    # 初始化栈
    def __init__(self):
        self.items = []

    # 判断栈是否为空
    def is_empty(self):
        return self.items == []

    # 返回栈顶
    def peek(self):
        return self.items[len(self.items) - 1]

    # 返回栈大小
    def size(self):
        return len(self.items)

    # 压栈
    def push(self, item):
        self.items.append(item)

    # 出栈
    def pop(self):
        return self.items.pop()

15、什么是蓝图,作用呢?

# blueprint把实现不同功能的module分开.
# 把一个大的application分割成各自实现不同功能的module.
# 在一个blueprint中可以调用另一个blueprint的view function, 但要加相应的blueprint名.

16、Flask中的session什么时候创建、什么时候销毁?

# 前提:
    不熟的话:记不太清了,应该是……
    熟悉的话:前两天恰好刚看过…….    
# 创建:
    当请求刚进来的时候,会将request和session封装成一个RequestContext()对象,
    接下来把这个对象通过LocalStack()放入内部的一个Local()(实现对数据隔离,类似threading.local) 对象中;
   因为刚开始 Local 的ctx 中的session是空的;
   所以,接着执行open_session,将cookie 里面的值拿过来,重新赋值到ctx中
  (Local用来存数据)
# 销毁:
    最后返回时,候执行 save_session() 将ctx 中的session读出来进行序列化,写到cookie
    然后给用户,接着把 ctx 移除掉(pop)

17、Local的作用?

-用于保存
    # 请求(RequestContext())上下文对象
    # App (AppContext())上下文对象

-并且可以做到”线程”间的数据隔离
    # 线程指: threading.local

18、LocalStack的作用?

# 将Local中保存的数据维护成一个栈(后进先出—弹夹)

例如:
{
    1234:{ stack:[ctx, ctx, ctx] }      
}

Django框架

19、Django请求生命周期

图示:http://www.cnblogs.com/bigtreei/p/8379635.html

20、对Django/flask框架的认识(Django和Flask区别)

# 口述

# Django:对于django来说,是一个大而全的框架,内部组件特别多,
  # 例如:ORM、admin、Form、ModelForm、中间件、信号、缓存、csrf等;
# Flask:而flask是一个微型框架,但可扩展性很强;如果开发简单程序,使用flask比较快捷;如果实现复杂功能,则需要引入一些组件;
  # 例如:flask-session\flask-SQLAlchemy\wtforms\flask-migrate\flask-script\blinker

# 他们两个都基于wsgi协议实现的,但默认使用的wsgi模块是不一样的;(Django:wsigref Flask:werkzurg)
# 还有一个显著的特点,他们处理请求方式不同:
  # Django:通过将请求封装成Request对象,再通过参数进行传递。
  # Flask:通过上下文管理机制实现。
    # 对了,感觉Flask的上下文管理还是挺有意思的。

延伸(可能会顺着问下去):

  • Django组件:
  • Flask组件、用途:
  • wsgi
  • 上下文管理:

21、你了解哪些框架?他们之间的区别?

21_1、Django和Flask,请求方式不同 
#Django: 请求方式为传参

#Flask: 请求方式为上下文管理机制
21_2、Django的请求生命周期?
# 请求进来

# 走到wsgi

# 走到中间件

# 路由匹配

# 执行相应的视图函数,ORM数据库操作

# 模板渲染成字符串

# 再经过中间件走回wsgi
21_3、什么是wsgi?
# 是web服务网关接口,是一套协议

  #目前接触的:

    # wsigref(Django,性能较低)

    # werkzurg(Flask,性能较低)

    # uwsig(性能较高、线上发布)

# 以上模块的本质:

  #实现wsgi协议的模块本质上是写了一个socket服务端,用来监听用户请求;
  #如果有请求进来,则将请求进行一次封装,然后将封装后的请求交给web框架来进行后续处理。
from wsgiref.simple_server import make_server

def run_server(environ, start_response):
    """
    environ: 封装了请求相关的数据
    start_response:用于设置响应头相关数据
    """
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
 
 
if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    httpd.serve_forever()
            
wsgi实现本质
class WSGIHandler(base.BaseHandler):
    request_class = WSGIRequest

    def __init__(self, *args, **kwargs):
        super(WSGIHandler, self).__init__(*args, **kwargs)
        self.load_middleware()

    def __call__(self, environ, start_response):
        # 请求刚进来之后 #
        
        set_script_prefix(get_script_name(environ))
        signals.request_started.send(sender=self.__class__, environ=environ)
        request = self.request_class(environ)
        response = self.get_response(request)

        response._handler_class = self.__class__

        status = '%d %s' % (response.status_code, response.reason_phrase)
        response_headers = [(str(k), str(v)) for k, v in response.items()]
        for c in response.cookies.values():
            response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
        start_response(force_str(status), response_headers)
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
        return response
Django源码实现wsgi功能
21_4、Django中间件的作用?用它做过什么?以及涉及的方法?
#a.中间件的作用?
  - 对所有的请求进行批量处理,在视图函数执行前后进行自定义操作。
#b.中间件的应用?
  - 登录验证
  - 权限处理
  - CORS跨域
  - 还有一些内置的:
     - csrf?
     - session?
     - 全站缓存(中间件2/4)(见下图)?
  - 另外还有一个就是处理跨域(前后端分离时,本地测试开发时使用的)
#c.中间件的方法( 5个方法)?
        1process_request(self, request)
        2process_view(self, request, callback, callback_args, callback_kwargs)
        3process_template_response(self, request, response)(当视图函数返回值对象中有render方法时,该方法才会被调用。)
        4process_exception(self, request, exception)
        5、process_response(self, request, response)
21_4_1、为什么要用缓存?
#将常用且不太频繁修改的数据放入缓存。
#以后用户再来访问,先去缓存查看是否存在,如果有就返回
#否则,去数据库中获取并返回给用户(再加入到缓存,以便下次访问)
21_4_2、Django内部支持哪些缓存?
#Django中提供了6种缓存方式:
    开发调试(不加缓存)
    内存
    文件
    数据库
    Memcache缓存(python-memcached模块)
    Memcache缓存(pylibmc模块)
                
#安装第三方组件支持redis:
    django-redis组件 
21_4_3、设置缓存有哪些?
#- 全站缓存
#- 视图函数缓存
#- 局部模板缓存
21_5、路由系统
#在url和视图函数对应关系中,根据当前请求url找到相应的函数。 
21_6、模板
索引: {{v.0}}
方法执行: {% for item in dic.items %} {%endfor%}
模板继承
自定义方法:
    - simple_tag
    - inclusion_tags
    - filter
21_7、视图函数
    - 遇到的难题:
      - CBV是添加csrf装饰器
      - 多数据库配置 allow_relation方法
    - FBV
      def index(request):
        pass
    - CBV(源码中走的 as_view)

      class IndexView(View):
      路由:IndexView.as_view()
    - CBV 和 FBV的区别是什么?  
      - 我认为没什么区别,他们的本质都是函数。因为CBV中.as_view()返回的是view函数,view函数中调用类的dispatch方法,在dispatch方法中通过反射执行get/post/delete/put等方法。
      - 如果非要说区别的话,CBV比较简洁,它的GET/POST等业务功能分别放在不同get/post函数中。而FBV则自己做判断进行区分。
    -使用CBV时的注意事项?
      -装饰器
      -csrf的装饰器要加到dispatch
from django.views import View
from django.utils.decorators import method_decorator

def auth(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

class UserView(View):
    
    @method_decorator(auth)
    def get(self,request,*args,**kwargs):
        return HttpResponse('...')
CBV装饰器使用注意
from django.views import View
    from django.utils.decorators import method_decorator
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    class UserView(View):

        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return HttpResponse('...')
        
或
    from django.views import View
    from django.utils.decorators import method_decorator
    from django.views.decorators.csrf import csrf_exempt,csrf_protect

    @method_decorator(csrf_exempt,name='dispatch')
    class UserView(View):

        def dispatch(self, request, *args, **kwargs):
            return HttpResponse('...')
csrf的装饰器  

 22、CSRF的原理是什么?

# #为了防止用户直接向服务端发起POST请求。    

# 用户先发送一个GET请求,获取csrf_token:Form表单中一个 隐藏的标签+cookie

# 发起POST请求时,需要携带之前发送给用户的CSRF_TOKEN:

# 在 process_view 方法中进行校验

23、向后台发送POST请求的方式有哪些?

  • Ajax
  • Postman
  • form表单
  • 爬虫:request.post()
<form method="POST">
    {% csrf_token %}
    <input type='text' name='user' />
    <input type='submit' />
</form>
form表单提交
$.ajax({
    url:'/index',
    type:'POST',
    data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'}
})

前提:引入jquery + 引入jquery.cookie 
$.ajax({
    url: 'xx',
    type:'POST',
    data:{name:'oldboyedu'},
    headers:{
        X-CSRFToken: $.cookie('csrftoken')
    },
    dataType:'json', // arg = JSON.parse('{"k1":123}')
    success:function(arg){
        
    }
})
Ajax提交
<body>
    <input type="button" οnclick="Do1();"  value="Do it"/>
    <input type="button" οnclick="Do2();"  value="Do it"/>
    <input type="button" οnclick="Do3();"  value="Do it"/>

    <script src="/static/jquery-3.3.1.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
            }
        });

         function Do1(){
            $.ajax({
                url:"/index/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
        }

         function Do2(){
            $.ajax({
                url:"/index/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
        }

         function Do3(){
            $.ajax({
                url:"/index/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
        }
    </script>
</body>
优化:Ajax提交

 24、Form和ModelForm的作用?区别?应用场景?

# 作用:
    - 对用户请求数据格式进行校验
    - 自动生成HTML标签
# 区别:
    # Form,字段需要自己手写。
        class Form(Form):
            xx = fields.CharField(.)
            xx = fields.CharField(.)
            xx = fields.CharField(.)
            xx = fields.CharField(.)
    # ModelForm,可以通过Meta进行定义
        class MForm(ModelForm):
            class Meta:
                fields = "__all__"
                model = UserInfo
                
# 应用:只要是客户端向服务端发送表单数据时,都可以进行使用,如:用户登录注册
# 问题:choice的数据如果从数据库获取可能会造成数据无法实时更新
# 答案:重写构造方法,在构造方法中重新去数据库获取值。

25、Django中都有哪些内置组件?

#例如:ORM、admin、Form、ModelForm、中间件、信号、缓存、csrf等,
#这些都是django内置的组件

26、这些组件中哪个组件最好?对哪个组件最熟悉?

#1、我感觉不能说哪个组件最好,因为他们各有所长,单独拿出来进行比较不合适;
#2、ORM用的最多,因为只要涉及到数据操作,基本都会用到ORM

27、ORM中你都记得哪些方法?(★★★★★)

#a、首先是增删改查这些,例如:.creat(),bukle_creat()

#b、然后是查询取值这块,values/values_list

#c、还有有F/Q这类复杂查询用法

#d、以及性能相关,例如:.prefetch_related()/select_related() #都可以用于连表,减少SQL查询次数

#e、再者是一些靠近原生SQL的用法,例如:extra、raw、execute等

28、django信号的作用?

#django的信号其实就是django内部为开发者预留的一些自定制功能的钩子。
#只要在某个信号中注册了函数,那么django内部执行的过程中就会自动触发注册在信号中的函数。
如: 
        
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    
#用信号做过什么?
    在数据库某些表中添加数据时,可以进行日志记录。

29、Django中的序列化?

#内置:
    from django.core import serializers
    
    #queryset = [obj,obj,obj]
    ret = models.BookType.objects.all()
     
    data = serializers.serialize("json", ret)
#json:
    import json

    #ret = models.BookType.objects.all().values('caption')
    ret = models.BookType.objects.all().values_list('caption')
     
    ret=list(ret)
     
    result = json.dumps(ret)
    
    #补充:
        - json.dumps(ensure_ascii=True)
        - json.dumps( cls=JSONEncoder)

30、admin & stark组件关系?

#- 为公司定制更适用于自己的组件: stark组件

31、ContentType的作用?以及应用场景?

#contenttype是django的一个组件(app),为我们找到django程序中所有app中的所有表并添加到记录中。

#可以使用他再加上表中的两个字段实现:一张表和N张表创建FK关系。
    - 字段:表名称
    - 字段:数据行ID
    
#应用:路飞表结构优惠券和专题课和学位课关联。

32、什么是幂等性?

# 一个接口通过1次相同的访问,再对该接口进行N次相同的访问时候,对资源不造影响,那么就认为接口具有幂等性。
比如:
    GET,  #第一次获取结果、第二次也是获取结果对资源都不会造成影响,幂等。
    POST, #第一次新增数据,第二次也会再次新增,非幂等。
    PUT,  #第一次更新数据,第二次不会再次更新,幂等。
    PATCH,#第一次更新数据,第二次不会再次更新,非幂等。
    DELTE,#第一次删除数据,第二次不在再删除,幂等。

 

33、实现远程数据交互的有哪些?

#- webservice, webservice是在rest api广泛引用之前大家使用的一个跨平台交互的接口。
#- restfull api
#- RPC

扩展:WCF他是创建了一个双工通道。

Django rest framework 框架

34、谈谈你对restfull 规范的认识?

# restful其实就是一套编写接口的协议,协议规定如何编写以及如何设置返回值、状态码等信息。
# 最显著的特点:
    restful: 给用户一个url,根据method不同在后端做不同的处理,比如:post 创建数据、get获取数据、put和patch修改数据、delete删除数据。
    no rest: 给调用者很多url,每个url代表一个功能,比如:add_user/delte_user/edit_user/
# 当然,还有协议其他的,比如:
    # 版本,来控制让程序有多个版本共存的情况,版本可以放在 url、请求头(accept/自定义)、GET参数
    # 状态码,200/300/400/500
    # url中尽量使用名词,restful也可以称为“面向资源编程”
    # api标示:
        api.luffycity.com
        www.luffycity.com/api/

34_1、状态码有哪些?

- 200 #请求成功
- 300
    - 301 #永久重定向
    - 302 #临时重定向
- 400
    - 403 #CSRF(跨域)
    - 404 #找不到页面
- 500  #内部服务器错误

34_2、method都有哪些?

# GET/POST/PUT/DELETE/PATCH/OPTIONS/HEADERS/TRACE(请求方式)

34_3、常见的请求头有哪些?

# GET
# POST
# PUT
# DELETE
# TRACE
# HEAD
# OPTIONS
# CONNECT

34_4、 你的restfull是怎么学的?

# 因为之前公司要写这样项目
    - 接口
    - 公司要做前后端分离的项目
    - 公司要做微信小程序的开发
# 所以就开始学习restful规范,看的技术文章 阮一峰的博客学到的规范。

35、用django写接口时,有没有用什么框架?

#- 使用 Django rest framework 框架
#- 以及原生CBV

36、为什么用rest framework框架?

#1、在编写接口时可以不使用django rest framework框架,

#2、如果不使用:也可以做,那么就可以django的CBV来实现,开发者编写的代码会更多一些。

#3、如果  使用:内部帮助我们提供了很多方便的组件,我们通过配置就可以完成相应操作,如:
            #a、序列化,可以做用户请求数据校验+queryset对象的序列化称为json
            #b、解析器,获取用户请求数据request.data,会自动根据content-type请求头的不能对数据进行解析
            #c、分页,将从数据库获取到的数据在页面进行分页显示。
            # 还有其他组件:
                #d、认证
                #e、权限
                #f、访问频率控制
                 

37、rest framework都有哪些组件?

#- 路由,自动帮助开发者快速为一个视图创建4个url
        www.oldboyedu.com/api/v1/student/$
        www.oldboyedu.com/api/v1/student(?P<format>\w+)$
        
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$
        
#- 版本处理
    - 问题:版本都可以放在那里?
            - url
            - GET 
            - 请求头 
#- 认证 
    - 问题:认证流程?

#- 权限 
    - 权限是否可以放在中间件中?以及为什么?

#- 访问频率的控制
    - 匿名用户可以真正的防止?无法做到真正的访问频率控制,只能把小白拒之门外。
      如果要封IP,使用防火墙来做。
      
    - 登录用户可以通过用户名作为唯一标示进行控制,如果有人注册很多账号,也无法防止。

#- 视图

#- 解析器 ,根据Content-Type请求头对请求体中的数据格式进行处理。request.data 

#- 分页

#- 序列化
    - 序列化
        - source
        - 定义方法
    - 请求数据格式校验

#- 渲染器
组件

38、rest framework 视图你都用过哪些基类?

#a. 继承 APIView
    # 这个类属于rest framework中顶层类,内部帮助我们实现了一些基本功能:
        # 认证、权限、频率控制,但凡是数据库、分页等操作都需要手动去完成,比较原始。

   class GenericAPIView(APIView)
        def post(...):
            pass 
        
#b. 继承 GenericViewSet(ViewSetMixin, generics.GenericAPIView)
    # 如果继承它之后,路由中的as_view需要填写对应关系 ---> .as_view({'get':'list','post':'create'})
    # 在内部也帮助我们提供了一些方便的方法:
        - get_queryset
        - get_object
        - get_serializer
    
    注意:要设置queryset字段,否则会抛出断言的异常。
    # 只提供增加功能
    class TestView(GenericViewSet):
        serializer_class = XXXXXXX
        def create(self,*args,**kwargs):
            pass # 获取数据并对数据进行操作

    
#c. 继承 
        - ModelViewSet
        - mixins.CreateModelMixin,GenericViewSet
        - mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet

    # 对数据库和分页等操作不用我们在编写,只需要继承相关类即可。
    
    示例:只提供增加功能
    class TestView(mixins.CreateModelMixin,GenericViewSet):
        serializer_class = XXXXXXX


类的继承关系

39、rest framework中的认证流程?

- 如何编写?写类并实现authticate
- 方法中可以定义三种返回值:
    - (user,auth),认证成功
    - None , 匿名用户
    - 异常 ,认证失败
- 流程:
    - dispatch 
    - 再去request中进行认证处理

40、rest framework中的访问频率控制?

# 匿名用户,根据用户IP或代理IP作为标识进行记录,为每一个用户在redis中创建一个列表
    {
        throttle_1.1.1.1:[1526868876.497521,152686885.497521...]
        throttle_1.1.1.2:[1526868876.497521,152686885.497521...]
        throttle_1.1.1.3:[1526868876.497521,152686885.497521...]
        throttle_1.1.1.4:[1526868876.497521,152686885.497521...]
        throttle_1.1.1.5:[1526868876.497521,152686885.497521...]
    }
    
    每个用户再来访问时,需要先去记录中剔除以及过期时间,再根据列表的长度判断是否可以继续访问。
    
    如何封IP:在防火墙中进行设置
# 注册用户,根据用户名或邮箱进行判断。
    {
        throttle_xxxx1:[1526868876.497521,152686885.497521...]
        throttle_xxxx2:[1526868876.497521,152686885.497521...]
        throttle_xxxx3:[1526868876.497521,152686885.497521...]
        throttle_xxxx4:[1526868876.497521,152686885.497521...]
    
    }
    
    每个用户再来访问时,需要先去记录中剔除以及过期时间,再根据列表的长度判断是否可以继续访问。

1分钟:40次
限流

41、渲染器中的坑?

#- 指定渲染器只用JSON
#- 视图:
    class UserView(...):
        queryset = []
        ...

42、assert (断言)是的作用?

#条件成立则继续往下,否则抛出异常;
#一般用于:满足某个条件之后,才能执行,否则应该抛出异常。

应用场景:rest framework

class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None

    lookup_field = 'pk'
    lookup_url_kwarg = None

    # The filter backend classes to use for queryset filtering
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

    # The style to use for queryset pagination.
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get_queryset(self):
        assert self.queryset is not None, (
            "'%s' should either include a `queryset` attribute, "
            "or override the `get_queryset()` method."
            % self.__class__.__name__
        )

        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            # Ensure queryset is re-evaluated on each request.
            queryset = queryset.all()
        return queryset
GenericAPIView

43、Django中用到的跨域?

#JsonP
#CORS

Websocket协议相关

44、websocket和http的区别?

websocket是一套类似于http的协议。

区别:
#     http协议:\r\n分割、请求头和请求体\r\n分割、无状态、短连接。
#websocket协议:\r\n分割、创建连接后不断开、 验证+数据加密;

 45、什么是websocket?

websocket是给浏览器新建一套协议。协议规定:浏览器和服务端连接之后不断开,以此可以完成:服务端向客户端主动推送消息。
websocket协议额外做的一些前提操作:
- 握手,连接前进行校验 - 发送数据加密

46、websocket的本质是?

 就是一个创建连接后不断开的socket

握手,魔法字符串
+加密 加密,payload_len=127/126/<=125 -> mask key
websocket是什么?
    websocket是一套类似于http的协议。
    扩展:
             http协议:\r\n分割、请求头和请求体\r\n分割、无状态、短连接。
        websocket协议:\r\n分割、创建连接后不断开、 验证+数据加密;
        
    websocket本质:
        - 就是一个创建连接后不断开的socket
        - 当连接成功之后:
            - 客户端(浏览器)会自动向服务端发送消息,包含: Sec-WebSocket-Key: iyRe1KMHi4S4QXzcoboMmw==
            - 服务端接收之后,会对于该数据进行加密:
                base64(sha1(swk + magic_string))
                
            - 构造响应头:
                HTTP/1.1 101 Switching Protocols\r\n
                Upgrade:websocket\r\n
                Connection: Upgrade\r\n
                Sec-WebSocket-Accept: 加密后的值\r\n
                WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n
    
            - 发给客户端(浏览器)
        - 建立:双工通道,接下来就可以进行收发数据
            - 发送的数据是加密,解密,根据payload_len的值进行处理:
                - payload_len <=125
                - payload_len ==126
                - payload_len ==127
            - 获取内容:
                - mask_key 
                - 数据 
                根据mask_key和数据进行位运算,就可以把值解析出来。
websocket扩展

47、不同框架在项目中通过什么实现websocket?

#django: channel
#flask:  gevent-websocket 
#tornado: 内置
a. 安装 
    pip3 install gevent-websocket 
    
    作用:
        - 处理Http、Websocket协议的请求 -> socket 
        - 封装Http、Websocket相关数据   -> request
b. 基本结构
    from geventwebsocket.handler import WebSocketHandler
    from gevent.pywsgi import WSGIServer
    
    
    @app.route('/test')
    def test():
        ws = request.environ.get('wsgi.websocket')
        ws.receive()
        ws.send(message)
        ws.close()
        return render_template('index.html')
                    
    if __name__ == '__main__':
        http_server = WSGIServer(('0.0.0.0', 5000,), app, handler_class=WebSocketHandler)
        http_server.serve_forever()
Flask中gevent-websocket示例
#后端:
    from geventwebsocket.handler import WebSocketHandler
    from gevent.pywsgi import WSGIServer
    from flask import Flask,render_template,request
    import pickle

    app = Flask(__name__)
    app.secret_key = 'xfsdfqw'


    @app.route('/index')
    def index():
        return render_template('index.html')


    WS_LIST = []

    @app.route('/test')
    def test():
        ws = request.environ.get('wsgi.websocket')
        if not ws:
            return '请使用WebSocket协议'
        # websocket连接已经成功
        WS_LIST.append(ws)
        while True:
            # 等待用户发送消息,并接受
            message = ws.receive()

            # 关闭:message=None
            if not message:
                WS_LIST.remove(ws)
                break

            for item in WS_LIST:
                item.send(message)

        return "asdfasdf"


    if __name__ == '__main__':
        http_server = WSGIServer(('0.0.0.0', 5000,), app, handler_class=WebSocketHandler)
        http_server.serve_forever()

#前端:
    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
        <style>
            .msg-item{
                padding: 5px;
                border: 1px;
                margin: 0 5px;
            }
        </style>
    </head>
    <body>
        <h1>首页</h1>
        <div>
            <h2>发送消息</h2>
            <input id="msg" type="text"  /> <input type="button" value="发送" οnclick="sendMsg()">
            <h2>接收消息</h2>
            <div id="container">

            </div>
        </div>

        <script src="/static/jquery-3.3.1.min.js"></script>
        <script>

            ws = new WebSocket('ws://192.168.12.42:5000/test');
            ws.onmessage = function (event) {
                var tag = document.createElement('div');
                tag.className = 'msg-item';
                tag.innerText = event.data;
                $('#container').append(tag);
            }

            function sendMsg() {
                ws.send($('#msg').val());
            }

        </script>
    </body>
    </html>
web聊天室示例

48、实时消息推送用什么实现?优缺点?

#轮询
    优点:简单
    缺点:请求次数多,服务器压力大,消息延迟
#长轮询
    优点:实时接收数据,兼容性好
    缺点:请求次数比原来少,但是相对原来也不少
#websocket
    优点:代码简单,不再重复创建连接
    缺点:兼容性没有长轮询好

Tornado框架

49、什么是Tornado?

#Tornado是一个轻量级的Web框架,异步非阻塞+内置WebSocket功能。
#安装:pip3 install tornado 

目标:通过一个线程处理N个并发请求。
    - 处理请求IO :牛逼起来
    - 处理非请求IO:傻逼起来

import tornado
from tornado.web import Application
from tornado.web import RequestHandler
from tornado.websocket import WebSocketHandler


class IndexHandler(RequestHandler):

    def get(self, *args, **kwargs):
        # self.write('Hello World')
        self.render('index.html')

    def post(self, *args, **kwargs):
        user = self.get_argument('user')
        self.write('成功')

WS_LIST = []
class MessageHandler(WebSocketHandler):

    def open(self, *args, **kwargs):
        WS_LIST.append(self)

    def on_message(self, message):
        for ws in WS_LIST:
            ws.write_message(message)

    def on_close(self):
        WS_LIST.remove(self)



settings = {
    'template_path':'templates',
    'static_path':'static',
}

app = Application([
    (r"/index", IndexHandler),
    (r"/message", MessageHandler),
],**settings)

if __name__ == '__main__':
    app.listen(address='0.0.0.0',port=9999)
    tornado.ioloop.IOLoop.instance().start()
tornado示例

50、tornado有哪些内部组件?

#内部自己实现socket
#路由系统 
#视图 
#模板 
#cookie 
#csrf

51、Tornado异步非阻塞本质?

视图函数yield一个futrue对象,futrue对象默认:
    self._done = False   ,请求未完成
    self._result = None  ,请求完成后返回值,用于传递给回调函数使用。

tornado就会一直去检测futrue对象的_done是否已经变成True。

如果IO请求执行完毕,自动会调用future的set_result方法:
            self._result = result
            self._done = True

参考:http://www.cnblogs.com/wupeiqi/p/6536518.html(自定义异步非阻塞web框架)

 

 MTV和MVC区别

52、MTV和MVC?

#MVC: model view controller

#MTV: model tempalte view 

 

转载于:https://www.cnblogs.com/bigtreei/articles/9026517.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值