2、python框架相關知識體系

Django框架

一、django框架、flask框架和Tornado框架的區別?

django框架,內置組件多,自身功能強大,是一個大而全的框架,ORM、Admin、中間件、Form、ModelFrom、信號、緩存、csrf等
flask框架,內置組件少,但第三方豐富,可擴展性強,是一個微小型框架,組件有flask-session、flask-SQLAlchemy、wtforms、flask-migrate、flask-script、blinker
相同點:
    兩個框架都是基於wsgi協議實現的,只是默認使用的wsgi模塊不同。 django:wsgiref模塊 flask:werkzurg模塊
不一樣點:他們各自處理請求的方式不一樣:
    django: 經過將請求封裝成Request對象,在依次經過中間件,在視圖中經過參數進行傳遞。
    flask:經過上下文管理實現。

Tornado框架:
  Tornado是一個輕量級的Web框架,主要功能:異步非阻塞+內置WebSocket

二、django框架的請求週期

a. wsgi, 建立socket服務端,用於接收用戶請求並對請求進行初次封裝。
b. 中間件,對全部請求在到來以前,響應以前定製一些操做。
c. 路由匹配,在url和視圖函數對應關係中,根據當前請求url找到相應的函數。
d. 執行視圖函數,業務處理【經過ORM去數據庫中獲取數據,再去拿到模板,而後將數據和模板進行渲染】
e. 再通過全部中間件
f. 經過wsgi將響應返回給用戶。javascript

2.1瀏覽器上輸入地址,回車而後發生了什麼? => Http請求生命週期 

一、進行域名解析獲取ip, 先去本地域名服務器,若是沒有再去根域名服務器
二、鏈接成功
三、瀏覽器發送數據
四、服務器接受到數據後處理並響應給瀏覽器
  -服務器在次過程當中處理流程較多,-django,flask等

三、什麼是WSGI?與uWSGI的區別

WSGI是web服務網關接口--->應用程序(web框架)與web服務器之間的一種接口css

實現了wsgi協議的模塊本質:編寫了socket服務端,用來監聽用戶請求,若是有請求到來,則將請求進行一次封裝,而後交給 web框架來進行下一步處理。html

模塊有:-wsgiref     -werkzurg    -uwsgi前端

uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換vue

代碼上線時,使用uWSGI:java

一、nginx 作爲代理服務器:負責靜態資源發送(js、css、圖片等)、動態請求轉發以及結果的回覆;python

二、uWSGI 作爲後端服務器:負責接收 nginx 請求轉發並處理後發給 Django 應用以及接收 Django 應用返回信息轉發給 nginx;mysql

三、Django 應用收到請求後處理數據並渲染相應的返回頁面給 uWSGI 服務器。jquery

四、中間件

做用:對全部的請求進行批量處理,能夠在視圖函數執行先後進行自定義操做linux

應用:

-用戶登陸驗證 --->若是使用裝飾器,就必須給每一個函數都添加,太繁瑣
-權限處理 --->用戶登陸成功,將該用戶全部的權限寫入session中,每次訪問時判斷該用戶是否有權限訪問當前的url,這樣就能夠將判斷用戶是否用權限的操做放入中間中
-內置應用
  -session
  -csrf --->跨站請求僞造,防止用戶直接向服務端發送POST請求。中間件攔截檢驗是否攜帶crsf_token
  -全局緩存 --->若是設置了緩存,則請求進來,經過中間件後,則直接去緩存中取數據,而後響應,若是此時的緩存中沒有數據,則走路由匹配、視圖函數,可是在響應時會先將數據放入到緩存當中
-跨域
  -cors --->瀏覽器的同源策略(不一樣的域名或不一樣的端口)先後端分離時,本地開發測試使用

五、csrf原理

一、瀏覽器向服務端發送GET請求,獲取csrf_token:  form表單中隱藏的input標籤+保存到cookie中(經過算法)
二、再次發送POST請求時,須要攜帶以前發給瀏覽器的csrf_token,用次crsf_token與cookie中的crsf_token作驗證
三、進行驗證:在process_view中驗證(由於只有在process_view中,才能獲得視圖函數,判斷函數是否須要驗證(加裝飾器能夠避免驗證))

 六、方法

porcess_request
porcess_view
porcess_template_response    只有在視圖函數的返回值中有render方法時才調用此方法
porcess_excepion             處理異常
porcess_response

七、發送POST請求的方法

  1. form表單
  2. ajax提交
  3. requests.post()
                方法一:
                    $.ajax({
                        url:'/index',
                        type:'POST',
                        #攜帶csrf_token
                        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){
                            
                        }
                    })
                    
                方法三:使用ajaxSetup,
                        <body>
                            <input type="button" onclick="Do1();"  value="Do it"/>
                            <input type="button" onclick="Do2();"  value="Do it"/>
                            <input type="button" onclick="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提交

八、基於django使用ajax發送post請求時,均可以使用哪一種方法攜帶csrf token?

data    headers    ajaxSetup()

九、路由

一、路由分發include:二級路由

二、路由系統中name的做用:反向解析

 url(r'^home', views.home, name='home')

  在模板中使用    {% url 'home' %}

  在視圖中使用  reverse(「home」)

十、 MTV和MVC

MVC: model   view(模塊)  controller (視圖)
MTV: model   tempalte    view

十一、視圖

一、CBV和FBV區別:

  本質上是沒有什麼區別的,由於它們都是經過對函數進行操做的,而CBV是經過.as_views()方法返回view函數,view函數再調用dispatch(), 在dispstch方法中在經過反射執行get、post、put、patch、delete方法的

二、處理csrf認證及CBV添加裝飾器

普通裝飾器能夠加在get、post等方法上

csrf裝飾器放在dispatch()上或直接加在類上

局部避免csrf的方式:
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    針對FBV:
        @csrf_exempt 
        def foo(request):
             return HttpResponse("foo")
         
    針對CBV:
        # 方式1
        @method_decorator(csrf_exempt,name="dispatch")
        class IndexView(View):
            # 方式2
            @method_decorator(csrf_exempt)
            def dispatch(self, request, *args, **kwargs):
                print("hello world")
                # 執行父類的dispatch方法
                res=super(IndexView,self).dispatch(request, *args, **kwargs)
                print("hello boy")
                return res
            
            @method_decoretor(裝飾器函數)  添加裝飾器
            def post(self,request,*args,**kwargs):
            
                return HttpResponse('OK')
        
View Code

十二、Django中request對象何時建立的?

當請求進來時,將請求相關的數據封裝到environ中,django項目啓動時,執行__call__,將environ賦值給request對象

wsgi:
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()
            
            
Django源碼:
    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
View Code

1三、 碰見的問題

- CBV時添加csrf裝飾器,是添加在dispatch上
- 多數據庫配置 allow_relation方法   進行連表

1四、ORM

一、增、刪、改、查

增:
models.UserInfo.objects.create()

obj = models.UserInfo(name='xx')
obj.save()

models.UserInfo.objects.bulk_create([models.UserInfo(name='xx'),models.UserInfo(name='xx')])

刪:
models.UserInfo.objects.all().delete()

改:
models.UserInfo.objects.all().update(age=18)
#在原來的基礎上添加1000
models.UserInfo.objects.all().update(salary=F('salary')+1000)

查:
filter()·        找不到返回[]
exclude()          排除

values()        字典    
values_list()   元祖

order_by()
order_by('-id')

anotate()      用於實現聚合group by查詢
aggregate() 聚合函數

exsit()     是否有結果
reverse()     反轉
distinct()  去重

返回具體的對象
first() 
laste() 
get()     找不到報錯
View Code

二、value餘value_list

value       返回一個字典

value_list 返回一元祖   (flat=Ture  此時返回一個列表)

三、F、Q

(1)F    用於比較,數字自增

# 查詢評論數大於收藏數的書籍
   from django.db.models import F
   Book.objects.filter(commnetNum__lt=F('keepNum'))

#將每一本書的價格提升30元
Book.objects.all().update(price=F("price")+30)

(2)Q   主要是構造複雜的查詢條件。查詢條件爲or(|),and($)

查詢做者名是小仙女或小魔女的
models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

四、性能優化

(1)select related

一、select_related主要針一對一和多對一關係進行優化。

二、select_related使用SQL的JOIN語句進行優化,經過減小SQL查詢的次數來進行優化、提升性能。

class Usertype(models.Model):
    title = models.CharField(max_length=32)

class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    ut = models.ForeignKey(to='UserType')

        
# 1次SQL
# select * from userinfo
   objs = UserInfo.obejcts.all()
    for item in objs:
        print(item.name)
        
# n+1次SQL
# select * from userinfo
    objs = UserInfo.obejcts.all()
    for item in objs:
        # select * from usertype where id = item.id 
        print(item.name,item.ut.title)
        

# 1次SQL
# select * from userinfo inner join usertype on userinfo.ut_id = usertype.id 
    objs = UserInfo.obejcts.all().select_related('ut')
    for item in objs:
        print(item.name,item.ut.title)
示例

(2)prftatch related

一、對於多對多字段(ManyToManyField)和一對多字段,可使用prefetch_related()來進行優化

二、prefetch_related()的解決方法是,分別查詢每一個表,而後用Python處理他們之間的關係。(若是鏈表過多,也會影響效率)

(3)only   僅取一條記錄中指定的數據(queryset[obj,obj,obj])      models.UserInfo.objects.only('username','id')

(4)defer    排除一條記錄指定的數據      (queryset[obj,obj])    models.UserInfo.objects.defer('username','id')

五、執行原生SQL

(1)extra  構造查詢條件,如子查詢

Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

(2)raw    執行sql語句

models.UserInfo.objects.raw('select * from userinfo')

(3)execute

   1.執行自定義SQL
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections['default'].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()

 五、using  指定數據庫

參考示例

1五、django中如何實現orm表中添加數據時建立一條日誌記錄

   使用信號

1六、 orm中的db first 與code first的區別?

db first    :先建立數據庫,再更新表模型

code first:先寫表模型,再更新數據庫

1七、django中如何根據數據庫表生成model中的類

一、settings中設置鏈接數據庫

二、python manage.py inspectdb > app/models.py 

1八、模板

一、模板繼承:{% extends 'layouts.html' %}

二、自定義方法

  1. filter                 只能傳遞兩個參數,能夠在if、for語句中使用
  2. simple_tag       能夠無線傳參,不能在if for中使用
  3. inclusion_tags  可使用模板和後端數據

三、xss攻擊:|safe   mark_safe  

1九、From和ModelFrom的做用、區別、應用場景

做用:   -用戶請求數據格式驗證

    -生產HTML標籤

區別:-From須要本身寫字段

   -ModelFrom經過Meta定義

場景:凡是須要進行表單數據驗證的  如:登陸驗證

20、django的Form組件中,若是字段中包含choices參數,請使用兩種方式實現數據源實時更新

重寫__init__和使用ModelChoiceField字段類型

from django.forms import Form
from django.forms import fields

方法一:從新__init__
class UserForm(Form):
    name = fields.CharField(label='用戶名',max_length=32)
    email = fields.EmailField(label='郵箱')
    ut_id = fields.ChoiceField(
        # choices=[(1,'二筆用戶'),(2,'悶騷')]
        choices=[]
    )

    def __init__(self,*args,**kwargs):
        super(UserForm,self).__init__(*args,**kwargs)
        
        # 每次實例化,從新去數據庫獲取數據並更新
        self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')

def user(request):
    if request.method == "GET":
        form = UserForm()
        return render(request,'user.html',{'form':form})

        
方法二:使用ModelChoiceField字段

from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
    name = fields.CharField(label='用戶名',max_length=32)
    email = fields.EmailField(label='郵箱')
    ut_id = ModelChoiceField(queryset=models.UserType.objects.all()) 
View Code

2一、django的Model中的ForeignKey字段中的on_delete參數有什麼做用

表關係是OneToOne,ForeignKey時,有on_delete參數,主要爲了不兩個表裏的數據不一致問題(關聯表中的對象被刪除後,此時表中的對象狀況)

Django2.0裏model外鍵和一對一的on_delete參數
在django2.0後,定義外鍵和一對一關係的時候須要加on_delete選項,此參數爲了不兩個表裏的數據不一致問題,否則會報錯:

TypeError: __init__() missing 1 required positional argument: 'on_delete'

舉例說明:

user=models.OneToOneField(User)
owner=models.ForeignKey(UserProfile)

須要改爲:

user=models.OneToOneField(User,on_delete=models.CASCADE)          --在老版本這個參數(models.CASCADE)是默認值
owner=models.ForeignKey(UserProfile,on_delete=models.CASCADE)    --在老版本這個參數(models.CASCADE)是默認值


參數說明:

on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五個可選擇的值

CASCADE:此值設置,是級聯刪除。

PROTECT:此值設置,是會報完整性錯誤。

SET_NULL:此值設置,會把外鍵設置爲null,前提是容許爲null。

SET_DEFAULT:此值設置,會把設置爲外鍵的默認值。

SET():此值設置,會調用外面的值,能夠是一個函數。
View Code

2二、爲何要用緩存

將經常使用且不太頻繁修改的數據放入緩存。
之後用戶再來訪問,先去緩存查看是否存在,若是有就返回
不然,去數據庫中獲取並返回給用戶(再加入到緩存,以便下次訪問)

2三、django中的緩存

Django中提供了6種緩存方式:
   --開發調試(不加緩存)
   --內存
   --文件
   --數據庫
   --Memcache緩存(python-memcached模塊)
   --Memcache緩存(pylibmc模塊)

安裝第三方組件支持redis:
   django-redis組件       設置settings文件

設置緩存:

  -全站緩存(中間件)

  -視圖函數緩存

  -局部模板緩存

2四、django中的信號

信號:django框架內部爲開發者預留下的一些自定製的鉤子,只要在某個信號中註冊了函數,則django內部執行時會自動觸發註冊在信號中的函數

Model signals
    pre_init                    # django的modal執行其構造方法前,自動觸發
    post_init                   # django的modal執行其構造方法後,自動觸發
    pre_save                    # django的modal對象保存前,自動觸發
    post_save                   # django的modal對象保存後,自動觸發
    pre_delete                  # django的modal對象刪除前,自動觸發
    post_delete                 # django的modal對象刪除後,自動觸發
    m2m_changed                 # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發
    class_prepared              # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發
Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate                # 執行migrate命令後,自動觸發
Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished            # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
Test signals
    setting_changed             # 使用test測試修改配置文件時,自動觸發
    template_rendered           # 使用test測試渲染模板時,自動觸發
Database Wrappers
    connection_created          # 建立數據庫鏈接時,自動觸發
View Code

應用場景:數據庫中表中的數據發生變化時,日誌記錄

2五、序列化

內置:

from django.core import serializers

#queryset = [obj,obj,obj]
ret = models.BookType.objects.all()

data = serializers.serialize("json", ret)

json:

- json.dumps(ensure_ascii=False)   #中文亂碼
- json.dumps( cls=JSONEncoder)  #自定義JSONEncoder,序列化特殊數據類型

2六、admin

對錶數據進行增刪改查  知識點:單例模式

- 爲公司定製更適用於本身的組件: stark組件

2七、ContentType

contenttype是django中的一個app,它能夠將django下全部app下的表記錄下來

一張表能夠動態的和N張表進行FK

應用:課程和專題課與間隔策略進行關聯

2八、django-debug-toolbar的做用

1、查看訪問的速度、數據庫的行爲、cache命中等信息。 
2、尤爲在Mysql訪問等的分析上大有用處(sql查詢速度)

2九、django中如何實現單元測試?

單元測試(Unittest)文本測試(Doctest)

rest_framework框架

30、restfull規範理解

- restful就是一套編寫接口的協議,協議規定了如何規範編寫接口以及設置返回值、狀態碼等信息。
- 最顯著的特色:
  restful: 給定一個url,根據method不一樣在後端作不一樣的處理,好比:post 建立數據、get獲取數據、put和patch修改數據、delete刪除數據。
  使用django中的URL: 就必須給調用者不少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/(主域名下,api功能簡單時)
- 協議 https
- 域名 
    - www.oldboy.com/api    主域名
    - api.oldboy.com        子域名
- 版本:
    - url:www.oldboy.com/api/v1
    - 請求頭中也能夠加
- URL資源,名詞
    - www.oldboy.com/api/v1/student

- 請求方式:
    - GET/POST/PUT/DELETE/PATCH/OPTIONS/HEADERS/TRACE
- 返回值:
    - www.oldboy.com/api/v1/student/    -> 結果集
    - www.oldboy.com/api/v1/student/1/  -> 單個對象
- URL添加條件
    - www.oldboy.com/api/v1/student?page=11&size=9
- 狀態碼:    
    - 200
    - 300
        - 301
        - 302
    - 400
        - 403
        - 404
    - 500
- 錯誤信息
    {
        code:1000,
        meg:'xxxx'
    }
- hyperlink
    {
        id:1
        name: ‘xiangl’,
        type: http://www.xxx.com/api/v1/type/1/
    }
View Code

31. 你的restful是怎麼學的?

- -由於以前公司要寫一個先後端分離的項目
- 因此就經過查看有關restful相關的技術類文檔和視頻,如: 阮一峯的博客學

3二、爲何要使用rest_framework

---rest—framework框架內部幫助咱們提供了不少組件,咱們只須要經過配置就能夠完成相應操做,如:
       - 序列化,能夠作用戶請求數據校驗+queryset對象的序列化稱爲json
       - 解析器,獲取用戶請求數據request.data,會自動根據content-type請求頭的不能對數據進行解析
       - 分頁,將從數據庫獲取到的數據在頁面進行分頁顯示。
       還有其餘:
         - 認證
         - 權限
         - 訪問頻率控制
---也可使用django的CBV來實現,只是須要編寫大量的代碼,下降開發效率。

3三、認證流程

一、編寫:寫類並實現authticate()
  - 方法中能夠定義三種返回值:
    -(user,auth),認證成功
    -  None , 匿名用戶
    -  異常 ,認證失敗
二、流程:
- 請求進來走dispatch方法,在dispatch方法中,執行initial()中執行perform_authentication(request)方法,

- 在認證中執行request.user

3四、頻率

- 請求進來走dispatch方法,在dispatch方法中,執行initial()中執行check_throttles(request)方法,

    def check_throttles(self, request):
        """
        Check if request should be throttled.
        Raises an appropriate exception if the request is throttled.
        """
        #遍歷throttle對象列表
        for throttle in self.get_throttles():
            #根據allow_request()的返回值進行下一步操做,返回True的話不執行下面代碼,標識不限流,返回False的話執行下面代碼,還能夠拋出異常
            if not throttle.allow_request(request, self):
                #返回False的話執行
                self.throttled(request, throttle.wait())

- 匿名用戶,根據用戶IP或代理IP做爲標識進行記錄,爲每個用戶在redis中建立一個列表
  
  每一個用戶再來訪問時,須要先去記錄中剔除以及過時時間,再根據列表的長度判斷是否能夠繼續訪問。 匿名用戶IP在防火牆中進行設置

- 註冊用戶,根據用戶名或郵箱進行判斷

    每一個用戶再來訪問時,須要先去記錄列表中剔除過時時間,再根據列表的長度判斷是否能夠繼續訪問。

1分鐘:40-60次

3五、視圖中均可以繼承哪些類

rest-frmawork視圖中能夠直接繼承10種類,外加View(object),能夠大體分爲三大部分
一、 繼承 APIView(View) 次類屬於rest framework中原始類,內部只是幫助咱們實現了基本功能:認證、權限、頻率控制,但凡涉及到數據庫、分頁等操做都須要手動去完成
二、 繼承 GenericViewSet(ViewSetMixin, generics.GenericAPIView)
    class GenericAPIView(APIView)
      def post(...):
          pass
    繼承此類,路由中的as_view()須要填寫對應關係 .as_view({'get':'list','post':'create'}),通常使用此類進行編寫,可擴展性強
    在內部也幫助咱們提供了一些方便的方法:
        - get_queryset
        - get_object
        - get_serializer
    
    注意:要設置queryset字段,不然會跑出斷言的異常。

    
三、 繼承 ModelViewSet()
  
對數據庫和分頁等操做不用咱們在編寫,只須要繼承相關類便可。此類封裝了大量的組件,操做起來簡單,可是擴展性較差 示例:若是隻提供增長功能,只繼承一下類便可
    - mixins.CreateModelMixin,GenericViewSet   
class TestView(mixins.CreateModelMixin,GenericViewSet):   serializer_class = XXXXXXX

3六、接口的冪等性?

對一個接口經過1次訪問以後,再對該接口進行N次相同的訪問時,對資源不造影響,那麼就認爲接口具備冪等性。(主要是第二次訪問時是否會形成傷害)
好比:
GET, 第一次獲取結果、第二次也是獲取結果對資源都不會形成影響,冪等。
POST,第一次新增數據,第二次也會再次新增,非冪等。
PUT, 第一次更新數據,第二次不會再次更新,冪等。
PATCH,第一次更新數據,第二次不會再次更新,非冪等。
DELTE,第一次刪除數據,第二次不在再刪除,冪等。

3七、assert的做用

條件成立,程序繼續執行,不然拋異常

應用場景:rest_framework中繼承類時,一、定義queryset 二、渲染器使用JSON

flask框架

一、 Flask內置功能依賴

0、基於wsgi協議下werkzurg模塊 

一、路由     @app.route("/login",method=["GET","POST"])

二、視圖      使用FBV

三、session    將簽名的session保存到cookie中

四、特殊裝飾器(相似於中間件)  @before_request   @after_request

五、message(閃現)    基於Session(先將數據寫入session,在session.pop("xx"))實現的用於保存數據的集合,其特色是:使用一次就刪除。

六、模板           使用jinja2

七、Blueprint(藍圖)     一、項目問價目錄的劃分 二、能夠統一劃分一類url   三、基於before_request(裝飾器)現實一類url的功能

二、Flask第三方組件

  flask:
      -flask-session    默認放入cookie,能夠放入redis
      -flask-migrate     數據化遷移
      -flask-script     自定義命令
      -blinker 信號


   公共: DBUtils       數據庫鏈接池
      wtforms      表單驗證+生成HTML標籤
      sqlalchemy   相似於django的orm
  自定義:Auth 參考falsk-login

三、 threading.local 做用?

爲每個線程開闢一條內存空間,用來存儲數據

做用:爲每個線程開闢一塊空間進行數據存儲
from threading import local
from threading import Thread
import time

# 示例化local對象
ret=local()

def task(s):
    global ret
    ret.value=s
    time.sleep(2)
    print(ret.value)


# 開啓10個線程
for i in range(10):
    t=Thread(target=task,args=(i,))
    t.start()
View Code

四、 Flask上下文管理流程以及和django比較?

  簡單來講,falsk上下文管理能夠分爲三個階段:
        1、請求進來時,將請求相關的數據放入上下文管理中
        2、視圖函數中,去上下文管理中取值,並操做
        3、請求響應,保存session,要將上下文管理中的數據清除
  
  詳細點來講:
        1、請求剛進來,將request,session封裝在RequestContext類中,將app,g封裝在AppContext類中,並經過LocalStack將requestcontext和appcontext放入Local類中
        2、視圖函數中,經過localproxy類中調用偏函數--->localstack--->local取值
        3、請求響應應時,先執行save.session()再各自執行pop(),將local中的數據清除
threading local和封裝

五、Flask中的session是何時建立,何時銷燬的? 

一、當請求進來時,會將requset和session封裝爲一個RequestContext對象,經過LocalStack將RequestContext放入到Local對象中,
二、由於請求第一次來session是空值,因此執行open_session,給session(uuid4())賦值,再經過視圖函數處理,
三、請求響應時執行save.session,將簽名session寫入cookie中,再去Local中的將數值pop掉。

六、Localstack做用

將local對象中的數據維護成一個棧【ctx,ctx】(先進後出)
         {
            「協程或線程的惟一標識」: { stack:[ctx,ctx,ctx,] }
         }
    
爲何維護成一個棧?
    一、當是web應用時:無論是單線程仍是多線程,棧中只有一個數據
       - 服務端單線程:
        {
        111:{stack: [ctx, ]}
          }
      - 服務端多線程:
        {
          111:{stack: [ctx, ]}
          112:{stack: [ctx, ]}
          }
    二、離線腳本和多app嵌套時:能夠在棧中放入多個數據,在任何狀況下均可以獲取到當前app請求對應的響應
            with app01.app_context():
                      print(current_app)
                      with app02.app_context():
                            print(current_app)
                      print(current_app)

七、 Flask中的g的做用?

g 至關於一次請求的全局變量,能夠對g進行相應的擴展(將用戶的權限賦值給g; 認證,將登錄用戶的標識賦值給g)
-請求進來時,將g和app封裝爲一個APPContext類,在經過LocalStack將Appcontext放入Local中,
-視圖函數中,經過
localproxy-->偏函數-->LocalStack-->local中取值,
-響應時將local中的g數據刪除:

八、 Flask中上下文管理主要涉及到了那些相關的類?並描述類主要做用?

RequestContext

AppContext

LocalStack

Local

LocalProxy

九、 Flask中多app應用是怎麼完成?

#對url進行處理和分發

from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.serving import run_simple

app01 = Flask('app01')
app02 = Flask('app02')


@app01.route('/login')
def login():
    return 'app01.login'


@app02.route('/index')
def index():
    return 'app02.index'

# 訪問"login"--->"http://localhost:5000/login"
# 訪問"index"--->"http://localhost:5000/app02/index"
dm = DispatcherMiddleware(app01, {
    '/app02': app02,
})

if __name__ == '__main__':
    run_simple('localhost', 5000, dm)
View Code

十、 原生SQL和ORM的區別?

orm關係對象映射

sql語句編寫較爲複雜,開發效率低,可是查詢速度快

orm操做方便,可提升開發效率,相對sql語句查詢速度低

十一、SQLAlchemy中的 session 的建立有幾種方式

一、直接建立session,多線程時須要爲每一個線程建立session

二、基於scoped_session建立 session = scoped_session(Session)  ,多線程時內部會自動爲每一個線程建立session  (好像是threading.local)

十二、SQLAlchemy如何執行原生SQL?

1三、SQLAchemy中如何爲表設置引擎和字符編碼?

1四、SQLAchemy中如何設置聯合惟一索引?

1五、解釋Flask框架中的Local對象和threading.local對象的區別?

Local中可使用協程中的惟一標識做爲棧中的key,粒度更細

1六、Flask中 blinker 是什麼?

信號

request_started = _signals.signal('request-started')                # 請求到來前執行
request_finished = _signals.signal('request-finished')              # 請求結束後執行
 
before_render_template = _signals.signal('before-render-template')  # 模板渲染前執行
template_rendered = _signals.signal('template-rendered')            # 模板渲染後執行
 
got_request_exception = _signals.signal('got-request-exception')    # 請求執行出現異常時執行
 
request_tearing_down = _signals.signal('request-tearing-down')      # 請求執行完畢後自動執行(不管成功與否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執行完畢後自動執行(不管成功與否)
 
appcontext_pushed = _signals.signal('appcontext-pushed')            # 請求上下文push時執行
appcontext_popped = _signals.signal('appcontext-popped')            # 請求上下文pop時執行
message_flashed = _signals.signal('message-flashed')                # 調用flask在其中添加數據時,自動觸發
View Code

1七、棧

class Stack(object):
    def __init__(self,size):
        self.stack=[]
        self.size=size

    def isfull(self):
        """
        判讀棧空
        :return:
        """
        if len(self.stack)==0:
            return True
        else:
            return False

    def isempty(self):
        """
        判斷棧滿
        :return: 
        """
        if len(self.stack)==self.size:
            return False
        else:
            return True

    def top(self,*args):
        if not self.isempty():
            raise Exception("已滿")
        else:
            self.stack.append(*args)

    def pop(self):
        if self.isfull():
            raise Exception("已空")
        else:
            self.stack.pop()


if __name__=="__main__":
    s=Stack(4)
    # for i in range(7):
    #     s.top(i)
    #     print(s.stack)

    for j in range(6):
        s.pop()
        print(s.stack)
View Code

1八、優先級隊列

import heapq
class PriorityQueue(object):
    #實現一個優先級隊列,每次pop優先級最高的元素
    def __init__(self):
        self.queue = []
        self.index = 0
    def push(self,item,priority):
        # 將priority和index結合使用,在priority相同的時候比較index,pop先進入隊列的元素
        heapq.heappush(self.queue,(priority,self.index,item))
        self.index += 1
    def pop(self):
        return heapq.heappop(self.queue)[-1]
if __name__ == '__main__':
    pqueue = PriorityQueue()
    pqueue.push('d',2)
    pqueue.push('f',3)
    pqueue.push('a',6)
    pqueue.push('s',4)
    pqueue.push('cao',9)
    print(pqueue.queue)
    print(pqueue.pop())
    print(pqueue.queue)
    print(pqueue.pop())
    print(pqueue.pop())
    print(pqueue.pop())
View Code

Tornado框架

一、簡述Tornado框架的特色。

異步非阻塞+websocket

二、簡述Tornado框架中Future對象的做用?

異步非阻塞本質:裝飾器+Futrue

        目標:經過一個線程處理N個併發請求。
        
        使用支持tornado異步非阻塞的單獨模塊:
            MySQL
            Redis
            SQLALchemy
        
        Tornado異步非阻塞本質:
       視圖函數yield一個futrue對象,
       futrue對象默認:
                self._done = False   ,請求未完成
                self._result = None  ,請求完成後返回值,用於傳遞給回調函數使用。
            
            tornado就會一直去檢測futrue對象的_done是否已經變成True。
            
            若是IO請求執行完畢,自動會調用future的set_result方法:
                        self._result = result
                        self._done = True

三、Tornado中靜態文件是如何處理的?


如: <link href="{{static_url("commons.css")}}" rel="stylesheet" />

static_url()自動去配置的路徑下找commons.css文件

四、Tornado操做MySQL使用的模塊?

torndb、mysqldb

五、Tornado操做redis使用的模塊?

Tornado-redis

六、簡述Tornado框架的適用場景

web聊天室,在線投票,處理高併發任務

redis

一、redis

redis它是將數據放在緩存中的,相比將數據放入到硬盤上,他的訪問速度更快,而且能夠將緩存中的數據定時更新到硬板中,同時增長了數據的安全性,它支持五大數據類型,字符串、數組、哈希、集合、有序集合

二、redis和memcached的區別

1)、存儲方式
Memecache把數據所有存在內存之中,斷電後會掛掉,數據不能超過內存大小。
Redis有部份存在硬盤上,這樣能保證數據的持久性。

2)、數據支持類型
Memcache只支持字符串類型
Redis支持五大數據類型

3)持久化、高可用、分佈式
redis支持數據持久化(RDB,AOF)、高可用、分佈式
memcached不支持,本身搭建

三、五種數據類型

方法

應用場景:
  字符串:rest farmework中的session, open_session.setex() save_session.get()
  列表 消息隊列、頻率、調度器、
  哈希 購物車
  集合 url去重
  有序集合 調度器的有優先級,排行榜

三、用redis作過什麼?

-購物車信息(商品設置超時時間)
-django-session
-rest frmawork 中的訪問頻率
-基於flask的websocket作的實時投票,使用redis作消息隊列 
-scrapy框架
  -URL去重    set()
  -調度器 先進先出、後進先出、優先級
  -pipelines 相似於生產者消費者模型
  -起始url 將起始url放入緩存中
-商品的熱點信息
-計數器      將修改的數據放入redis中再定時更新到數據庫中
-排序      有序集合

四、redis中數據庫默認是多少個db 及做用?

0-15個庫,默認的db0單庫

五、python操做redis模塊

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}
            # "PASSWORD": "密碼",
        }
    },
}

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'  # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置
View Code

五、爲何redis要作主從複製?

目的:是對redis作高可用,爲每個redis實例建立一個備份稱爲slave,主redis進行寫操做,從redis作讀操做,而且讓主和從之間進行數據同步,
優勢:
  - 性能提升,從分擔了主的壓力。保證了數據的安全性
  - 高可用,一旦主redis掛了,直接讓從代替主。
存在問題:當主掛了以後,須要人爲操做將從變成主。

數據同步機制:
主從剛剛鏈接的時候,進行全量同步;全同步結束後,進行增量同步。固然,若是有須要,slave 在任什麼時候候均可以發起全量同步。
redis 策略是,不管如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。

六、redis的sentinel是什麼?

一、自動在主從redis之間進行切換
二、檢測主從中 主是否掛掉,且超過一半的sentinel檢測到主掛掉以後才進行切換將從redis變爲主redis。
三、若是主修復好了,再次啓動時候,會變成從。

七、redis的cluster是什麼?

集羣方案:
    - redis cluster 官方提供的集羣方案。
    - codis,豌豆莢技術團隊。
    - twemproxy,Twiter技術團隊。
   -程序 (一致性哈希 hash-ring)   redis cluster的原理?
- 基於分佈式集羣來完成。(不一樣任務交給不一樣的redis處理) - redis將全部能放置數據的地方建立了 16384 個哈希槽。 - 若是設置集羣的話,就能夠爲每一個實例分配哈希槽: - 192.168.1.200-5000- 192.168.1.215001-10000- 192.168.1.2210001-16384- 之後想要在redis中寫值時, set k1 123 將k1經過crc16的算法,將k1轉換成一個數字。而後再將該數字和16384求餘,若是獲得的餘數 3000,那麼就將該值寫入到 192.168.1.20 實例中。

八、什麼是codis和twemproxy及做用?

實現redis分佈式集羣

九、什麼是一致性哈希?Python中是否有相應模塊?

一致性哈希:是一種分佈式算法,將任務均勻的分佈到不一樣的服務器上,經常使用於負載均衡,

hash_ring    將key利用crc32------>數字------>數字和服務器數取餘-------->放入服務器對應的數值區間

十、redis是否能夠作持久化?

RDB持久化  
  -每隔一段時間對redis進行一次持久化(基於時間點快照的方式,複用方式進行數據持久化)
  -效率較高,數據不完整,安全性不高

AOF持久化
  -把全部命令保存起來,若是想到從新生成到redis,那麼就要把命令從新執行一次。
  -效率相對較低,安全性較高

十一、redis的過時策略

.一、MySQL ⾥裏里有 2000w 數據,redis 中只存 20w 的數據,如何保證 redis 中都是熱點數據

voltile-lru:    從已設置過時時間的數據集(server.db[i].expires)中挑選最近頻率最少數據淘汰
volatile-ttl:   從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰
volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰

allkeys-lru:       從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:    從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據

十二、redis的分佈式鎖實現。

單太redis時,可使用watch
對多臺redis進行操做時,加鎖並設置超時時間,保證在此期間只有你一我的對redis操做,

----流程
- 寫值{key:"sfdfff"}加鎖並設置超時時間 - 超過一半的redis實例設置成功,就表示加鎖完成。
-解鎖 執行lua腳本,用key檢測每一個redis中是否有次key,有則刪除
- 使用:安裝redlock-py from redlock import Redlock   Redlock算法 dlm = Redlock( [ {"host": "localhost", "port": 6379, "db": 0}, {"host": "localhost", "port": 6379, "db": 0}, {"host": "localhost", "port": 6379, "db": 0}, ] ) # 加鎖,acquire my_lock = dlm.lock("my_resource_name",10000) if my_lock: # J進行操做 # 解鎖,release dlm.unlock(my_lock) else: print('獲取鎖失敗')

1三、檢測數據:watch

監聽一個數據,下次提交時,若是中間有人對此數據修改,則會報錯

- 經過redis的watch實現
    import redis
    conn = redis.Redis(host='127.0.0.1',port=6379)

    # conn.set('count',1000)
    val = conn.get('count')
    print(val)

    with conn.pipeline(transaction=True) as pipe:

        # 先監視,本身的值沒有被修改過
        conn.watch('count')

        # 事務開始
        pipe.multi()
        old_count = conn.get('count')
        count = int(old_count)
        print('如今剩餘的商品有:%s',count)
        input("問媳婦讓不讓買?")
        pipe.set('count', count - 1)

        # 執行,把全部命令一次性推送過去
        pipe.execute()
View Code

1四、事務

將一部分執行命令進行批量操做,

import redis

pool = redis.ConnectionPool(host='10.211.55.4', port=6379)

conn = redis.Redis(connection_pool=pool)

# pipe = r.pipeline(transaction=False)
pipe = conn.pipeline(transaction=True)
# 開始事務
pipe.multi()

pipe.set('name', 'alex')
pipe.set('role', 'sb')
pipe.lpush('roless', 'sb')

# 提交
pipe.execute()
View Code

1五、發佈者與訂閱者、消息隊列

發佈者:
    import redis

    conn = redis.Redis(host='127.0.0.1',port=6379)
    conn.publish('104.9MH', "hahahahahaha")
訂閱者:
    import redis

    conn = redis.Redis(host='127.0.0.1',port=6379)
    pub = conn.pubsub()
    pub.subscribe('104.9MH')

    while True:
        msg= pub.parse_response()
        print(msg)
            

                        
發佈訂閱

發佈訂閱:只要發佈者發佈任務則全部訂閱者都會接受到此任務。

消息隊列:隊列中放一個任務,則只有一個進程取任務

發佈訂閱和簡單的消息隊列區別在於,發佈訂閱會將消息發送給全部的訂閱者,而消息隊列中的數據被消費一次便消失。

因此,RabbitMQ實現發佈和訂閱時,會爲每個訂閱者建立一個隊列,而發佈者發佈消息時,會將消息放置在全部相關隊列中。

1六、如何基於redis實現消息隊列?

在線投票

1七、寫代碼,基於redis的列表實現 先進先出、後進先出隊列、優先級隊列

import heapq
class PriorityQueue(object):
    """實現一個優先級隊列,每次pop優先級最高的元素"""
    def __init__(self):
        self._queue = []
        self._index = 0
    def push(self,item,priority):
        # 將priority和index結合使用,在priority相同的時候比較index,pop先進入隊列的元素
        heapq.heappush(self._queue,(-priority,self._index,item))
        self._index += 1
    def pop(self):
        return heapq.heappop(self._queue)[-1]
if __name__ == '__main__':
    pqueue = PriorityQueue()
    pqueue.push('d',2)
    pqueue.push('f',3)
    pqueue.push('a',6)
    pqueue.push('s',2)
    print(pqueue.pop())
    print(pqueue.pop())
    print(pqueue.pop())
    print(pqueue.pop())
View Code

1八、若是一個字典在redis中保存了10w個值,我須要將全部值所有循環並顯示,請問如何實現?

def list_scan_iter(name,count=3):
    start = 0
    while True:
        result = conn.lrange(name, start, start+count-1)
        start += count
        if not result:
            break
        for item in result:
            yield item

for val in list_scan_iter('num_list'):
    print(val)

列表、集合、有序集合使用scan_iter

1九、如何高效的找到redis中全部以oldboy開頭的key?

keys(pattern="*")
# 根據模型獲取redis的name
 
# 更多:
    # KEYS * 匹配數據庫中全部 key 。
    # KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
    # KEYS h*llo 匹配 hllo 和 heeeeello 等。
    # KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo

Http協議

一、Http協議

一、Http協議是基於tcp協議之上的短鏈接、無狀態請求,規定數據之間\r\n分割,請求頭與請求體\r\n\r\n分割

二、請求頭:Host  Content-Type   User_Agent  method  referer  Date  cookie  

三、狀態碼

 成功

    200    成功

    202    服務器已接受請求,但還沒有處理
 重定向:

    301  永久重定向

    302  臨時重定向

 客戶端: 

    400   客戶端請求有語法錯誤,不能被服務器所理解

    401   請求未經受權,這個狀態代碼必須和WWW-Authenticate報頭域一塊兒使用 
    403   服務器收到請求,可是拒絕提供服務

    404   請求資源不存在,eg:輸入了錯誤的URL

 服務器:

    500   服務器發生不可預期的錯誤

    503 服務器當前不能處理客戶端的請求,一段時間後可能恢復正常
View Code 

四、請求方式

1    GET    請求指定的頁面信息,並返回實體主體。
2    HEAD    相似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭
3    POST    向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。
4    PUT    從客戶端向服務器傳送的數據取代指定的文檔的內容。
5    DELETE    請求服務器刪除指定的頁面。
6    CONNECT    HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
7    OPTIONS    容許客戶端查看服務器的性能。
8    TRACE    回顯服務器收到的請求,主要用於測試或診斷。
View Code

二、 HTTPS

  Http: 80端
  https: 443端口
    - 自定義證書
      - 服務端:建立一對證書
      - 客戶端:必須攜帶證書
    - 購買證書
      - 服務端: 建立一對證書,-將公鑰交給機構
      - 客戶端: 去機構獲取證書,數據加密後發給我們的服務單

三、什麼是websocket

  一、websocket協議是基於http的協議之上的,只是客戶端與服務端創建鏈接以後將再也不斷開,實現服務端向客戶端主動發送請求

    -進行數據通訊前先進行校驗(握手)

    -發送的數據都是加密的

  二、websocket本質      

 
 
  1. 首先,客戶端發起 http請求,通過3次握手後,創建起TCP鏈接;http請求裏存放WebSocket支持的版本號等信息,如:Upgrade、Connection、WebSocket-Version等;
  2. 而後,服務器收到客戶端的握手請求後,一樣採用HTTP協議回饋數據;
  3. 最後,客戶端收到鏈接成功的消息後,開始藉助於TCP傳輸信道進行全雙工通訊。
1、建立一個創建鏈接以後不斷開的socket

2、建立鏈接(握手)

  -客戶端向服務端發送請求

  -服務端獲取請求頭中的Sec-WebSocket-key的值,將此值+magic_string(魔法字符串)進行hashlib和base64加密

  -構造響應頭,裏面包含Sec-WebSocket-Accept: 加密後的值

  -返送給客戶端

  -客戶端再拿到加密的數據,解密進行驗證

3、鏈接創建成功後:創建雙工通道(同一時間,便可發送數據也可接受數據),進行數據通訊

  -發送的數據都是加密的,解密後,根據payload_len的值獲取內容(payload_len的值至關於報頭)

    -payload_len <=125

    -payload_len ==126

    -payload_len ==127

  -將獲取的內容分爲

    -mask_key

    -數據

    根據mask_key和數據進行位運算,最後解析出數據

  三、websocket的應用----但是實現客戶端實時監聽服務端的數據變化的操做

如:實時消息推送
- 輪詢   優勢:代碼簡單; 缺點:請求次數多,服務器壓力大,消息延遲。 - 長輪詢   優勢:實時接收數據,兼容性好;     缺點:請求次數相對輪詢減小。 - websocket   優勢:代碼簡單,再也不反覆建立鏈接。      缺點:兼容性差,不支持IE。

四、websocket與http協議的聯繫 ?

相同點:

  一、websocket和http都是基於TCP協議的

  二、都是屬於應用層的

不一樣點:

  1.  WebSocket是雙向通訊協議,模擬Socket協議,能夠雙向發送或接受信息。HTTP是單向的。
  2.    WebSocket是須要瀏覽器和服務器握手進行創建鏈接的。而http是瀏覽器發起向服務器的鏈接,服務器預先並不知道這個鏈接。

聯繫:

  一、WebSocket在創建握手時,數據是經過HTTP傳輸的。可是創建以後,在真正傳輸時候是不須要HTTP協議的。

五、三大框架如何實現websocket

  - django: channel
  - flask: gevent-websocket
  - tornado: 內置

六、輪詢與長輪詢

一、輪詢

  經過定時器讓客戶端每隔幾秒就向服務端發送一次請求

二、長輪詢

  客戶端向服務端發送一次請求,瀏覽器會將次請求夯住一段時間,若是有數據返回則當即響應,若是在此時間內沒有數據返回則斷開鏈接,客戶端再次發送請求

  ps:利用queue和redis實現夯住請求

三、輪詢的目的

  由於http請求是短鏈接無狀態的,服務端沒法實時向客戶端發送請求

  因此客戶端能夠利用輪詢和長輪詢向服務端實時發送請求

七、如何建立響應式佈局?

一個網站能夠兼容多個終端(根據分辨率不一樣自動匹配)

@media (min-width: 768px){
    .pg-header{
        background-color: green;
    }
}
@media (min-width: 992px){
    .pg-header{
        background-color: pink;
    }
}
View Code

八、你曾經使用過哪些前端框架?

Jquery

BootStrap

vue.js   Angular.js   React.js

九、什麼是ajax請求?並使用jQuery和XMLHttpRequest對象實現一個ajax請求。

ajax:異步請求+局部刷新

jquery:$.ajax()

xml    :   var xmlHttp = new XMLHttpRequest()

十、vuex的做用?

vuex維護了一個「全局變量"    基於vue_cookies能夠作用戶登陸、註銷   

使用Vuex只需執行 Vue.use(Vuex),並在Vue的配置中傳入一個store對象的示例(vue.store)

十、vue中的路由(router)的攔截器的做用?

能夠作權限

十一、axios的做用?

相似於ajax

十二、列舉vue的常見指令。

v-html   插入html

v-text    在元素中插入值

v-if   v-else

v-show

v-for   

v-on   監聽

v-bind   綁定

v-model    把input的值和變量綁定了,實現了數據和視圖的雙向綁定 

1三、簡述jsonp及實現原理?

自定義一個script標籤,調用回調函數, 後端返回一個函數()

jsop只能get請求

1四、是什麼cors ?

      添加響應頭

Git

一、git常見命令做用:

https://www.cnblogs.com/caochao-/articles/8823080.html

二、簡述如下git中stash命令做用以及相關其餘命令。

三、git 中 merge 和 rebase命令 的區別。

merge:會將不一樣分支的提交合併成一個新的節點,以前的提交分開顯示,注重歷史信息、能夠看出每一個分支信息,基於時間點 , 遇到衝突,手動解決,再次提交

rebase:將兩個分支的提交結果融合成線性,不會產生新的節點,注重開發過程,                                   遇到衝突,手動解決,繼續操做

參考

四、公司如何基於git作的協同開發?

1、大家公司的代碼review分支怎麼作?誰來作?
        答:組長建立review分支,咱們小功能開發完以後,合併到review分支
            交給老大(小組長)來看,
            你組長不開發代碼嗎?
                他開發代碼,可是它只開發核心的東西,任務比較少。
                或者抽出時間,咱們一塊兒作這個事情
2、大家公司協同開發是怎麼協同開發的?
        每一個人都有本身的分支,階段性代碼完成以後,合併到review,而後交給老大看

六、git如何實現v1.0 、v2.0 等版本的管理?

 在命令行中,使用「git tag –a tagname –m 「comment」能夠快速建立一個標籤。須要注意,命令行建立的標籤只存在本地Git庫中,還須要使用Git push –tags指令發佈到TFS服務器的Git庫中

參考

七、什麼是gitlab?

  gitlab是公司本身搭建的項目代碼管理平臺

八、github和gitlab的區別?

  gitHub是一個面向開源及私有軟件項目的託管平臺

  gitlab是公司本身搭建的項目託管平臺

九、如何爲github上牛逼的開源項目貢獻代碼?

十、git中 ".gitignore"文件的做用?

  設置哪些文件不須要添加到版本管理中  (好比Python的.pyc文件和一些包含密碼的配置文件等)

十一、什麼是敏捷開發?

敏捷開發:是一種以人爲核心、迭代、按部就班的開發方式。

它並非一門技術,而是一種開發方式,也就是一種軟件開發的流程。它會指導咱們用規定的環節去一步一步完成項目的開發。由於它採用的是迭代式開發,因此這種開發方式的主要驅動核心是人

十二、簡述 jenkins 工具的做用?

Jenkins 是一個可擴展的持續集成引擎。

主要用於:

  • 持續、自動地構建/測試軟件項目。
  • 監控一些定時執行的任務。

1三、公司如何實現代碼發佈?

     nginx+uwsgi+django

參考

1四、簡述 RabbitMQ、Kafka、ZeroMQ的區別?

參考

1五、RabbitMQ如何在消費者獲取任務後未處理完前就掛掉時,保證數據不丟失?

參考

爲了預防消息丟失,rabbitmq提供了ack,即工做進程在收到消息並處理後,發送ack給rabbitmq,告知rabbitmq這時候能夠把該消息從隊列中刪除了。若是工做進程掛掉 了,rabbitmq沒有收到ack,那麼會把該消息 從新分發給其餘工做進程。不須要設置timeout,即便該任務須要很長時間也能夠處理。

ack默認是開啓的,工做進程顯示指定了no_ack=True

1六、RabbitMQ如何對消息作持久化?

一、建立隊列和發送消息時將設置durable=Ture,若是在接收到消息尚未存儲時,消息也有可能丟失,就必須配置publisher confirm

channel.queue_declare(queue='task_queue', durable=True)

二、返回一個ack,進程收到消息並處理完任務後,發給rabbitmq一個ack表示任務已經完成,能夠刪除該任務

三、鏡像隊列:將queue鏡像到cluster中其餘的節點之上。在該實現下,若是集羣中的一個節點失效了,queue能自動地切換到鏡像中的另外一個節點以保證服務的可用性

1七、RabbitMQ如何控制消息被消費的順序?

默認消息隊列裏的數據是按照順序被消費者拿走,例如:消費者1 去隊列中獲取 奇數 序列的任務,消費者2 去隊列中獲取 偶數 序列的任務。

channel.basic_qos(prefetch_count=1) 表示誰來誰取,再也不按照奇偶數排列(同時也保證了公平的消費分發)

1八、如下RabbitMQ的exchange type分別表明什麼意思?如:fanout、direct、topic。

amqp協議中的核心思想就是生產者和消費者隔離,生產者從不直接將消息發送給隊列。
生產者一般不知道是否一個消息會被髮送到隊列中,只是將消息發送到一個交換機。
先由Exchange來接收,而後Exchange按照特定的策略轉發到Queue進行存儲。
同理,消費者也是如此。Exchange 就相似於一個交換機,轉發各個消息分發到相應的隊列中。

type=fanout 相似發佈者訂閱者模式,會爲每個訂閱者建立一個隊列,而發佈者發佈消息時,會將消息放置在全部相關隊列中

type=direct 隊列綁定關鍵字,發送者將數據根據關鍵字發送到消息exchange,exchange根據 關鍵字 斷定應該將數據發送至指定隊列。

type=topic  隊列綁定幾個模糊的關鍵字,以後發送者將數據發送到exchange,exchange將傳入」路由值「和 」關鍵字「進行匹配,匹配成功,則將數據發送到指定隊列。

發送者路由值              隊列中
old.boy.python          old.*  -- 不匹配    *表示匹配一個
old.boy.python          old.#  -- 匹配      #表示匹配0個或多個

1九、簡述 celery 是什麼以及應用場景?

 celery是python開發的一個分佈式任務隊列模塊,自己本不支持消息傳遞,依賴於redis、rabbitmq(官方推薦)

一、當用戶觸發一個操做須要較長時間才能執行完成的任務時,就能夠交給Celery異步執行,執行完再返回給用戶。這段時間用戶不須要等待,提升了網站的總體吞吐量和響應時間。

二、定時任務,好比天天檢測一下大家全部客戶的資料,若是發現今天 是客戶的生日,就給他發個短信祝福

20、簡述celery運行機制。

任務模塊 Task

包含異步任務和定時任務。其中,異步任務一般在業務邏輯中被觸發併發往任務隊列,而定時任務由 Celery Beat 進程週期性地將任務發往任務隊列。

消息中間件 Broker

Broker,即爲任務調度隊列,接收任務生產者發來的消息(即任務),將任務存入隊列。Celery 自己不提供隊列服務,官方推薦使用 RabbitMQ 和 Redis 等。

任務執行單元 Worker

Worker 是執行任務的處理單元,它實時監控消息隊列,獲取隊列中調度的任務,並執行它。

任務結果存儲 Backend

Backend 用於存儲任務的執行結果,以供查詢。同消息中間件同樣,存儲也可以使用 RabbitMQ, redis 和 MongoDB 等。
View Code

2一、celery如何實現定時任務?

一、配置文件,設置beat_schedule

 二、程序控制 經過 crontab 的對象

參考

2二、簡述 celery多任務結構目錄?

參考

2三、celery中裝飾器 @app.task 和 @shared_task的區別?

 @shared_task爲全部的celery對象,建立任務

 @app.task爲單個celery對象建立任務

scrapy框架

一、簡述 requests模塊的做用及基本使用?

獲取網站html或xml文本

二、簡述 beautifulsoup模塊的做用及基本使用?

將html或xml標籤進行解析

參考

三、簡述 seleninu模塊的做用及基本使用?

Selenium 是一個用於Web應用程序測試的工具,他的測試直接運行在瀏覽器上,模擬真實用戶,按照代碼作出點擊、輸入、打開等操做

爬蟲中使用他是爲了解決requests沒法解決javascript動態問題

參考

四、scrapy框架中各組件的工做流程?

參考

五、在scrapy框架中如何設置代理(兩種方法)?

六、scrapy框架中如何實現大文件的下載?

七、scrapy中如何實現限速?

八、scrapy中如何實現暫定爬蟲?

九、scrapy中如何進行自定製命令?

十、scrapy中如何實現的記錄爬蟲的深度?

十一、scrapy中的pipelines工做原理?

  爬蟲spiders中 yield item 

十二、scrapy的pipelines如何丟棄一個item對象?

  raise DropItem()

1三、簡述scrapy中爬蟲中間件和下載中間件的做用?

1四、scrapy-redis組件的做用?

實現了分佈式爬蟲,有url去重、調度器、數據持久化

1五、scrapy-redis組件中如何實現的任務的去重?

1六、scrapy-redis的調度器如何實現任務的深度優先和廣度優先?

廣度優先:先進先出(默認)有序集合

深度優先:先進後出

1七、簡述 vitualenv 及應用場景?

vitualenv 是一個獨立的python虛擬環境

如:當前項目依賴的是一個版本,可是另外一個項目依賴的是另外一個版本,這樣就會形成依賴衝突,而virtualenv就是解決這種狀況的,virtualenv經過建立一個虛擬化的python運行環境,將咱們所需的依賴安裝進去的,不一樣項目之間相互不干擾

參考

1八、簡述 pipreqs 及應用場景?

能夠經過對項目目錄掃描,自動發現使用了那些類庫,而且自動生成依賴清單。

pipreqs ./     生成requirements.txt

 雜七雜八

一、在Python中使用過什麼代碼檢查工具?

  pylint

二、簡述 saltstack、ansible、fabric、puppet工具的做用?

三、B Tree和B+ Tree的區別?

四、請列舉常見排序並經過代碼實現任意三種。

選擇、插入、

五、請列舉常見查找並經過代碼實現任意三種。

六、請列舉你熟悉的設計模式?

七、有沒有刷過leetcode?

  沒有    

八、列舉熟悉的的Linux命令。

點擊

九、公司線上服務器是什麼系統?

公司開發環境:
    1. windows
        - 在windows上開發【坑】
        - 代碼部署在linux :centos
    2. 雙系統
        - windows
        - linux: ubuntu+桌面版
        - linux: centos+桌面版
        
        - 代碼部署在linux :centos
    3. mac 
        - linux:mac 
        - 代碼部署在linux :centos
    4. vim開發
        - 經過vim在:centos
        - 代碼部署在linux :centos
View Code

十、解釋 PV、UV 的含義?

PV:訪問量, 即頁面瀏覽量或點擊量,衡量網站用戶訪問的網頁數量;在必定統計週期內用戶每打開或刷新一個頁面就記錄1次,屢次打開或刷新同一頁面則瀏覽量累計。

UV:獨立訪客,統計1天內訪問某站點的用戶數(以cookie爲依據);訪問網站的一臺電腦客戶端爲一個訪客

十一、解釋 QPS的含義?

QPS:每秒查詢率QPS是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準,在因特網上,做爲域名系統服務器的機器的性能常常用每秒查詢率來衡量

TPS:是軟件測試結果的測量單位。一個事務是指一個客戶機向服務器發送請求而後服務器作出反應的過程。客戶機在發送請求時開始計時,收到服務器響應後結束計時,以此來計算使用的時間和完成的事務個數。

十二、supervisor的做用?

Supervisor是一個進程管理工具

用途就是有一個進程須要每時每刻不斷的跑,可是這個進程又有可能因爲各類緣由有可能中斷。當進程中斷的時候我但願能自動從新啓動它,此時,用到Supervisor的fork/exec的方式

1三、簡述SSH的整個過程。

將傳輸的數據加密並壓縮,客戶端提供了口令驗證和密鑰驗證

1四、有問題都去那些找解決方案?

stackoverflow

git

知乎

思否

bing

1五、是否有關注什麼技術類的公衆號?

python之禪
碼農翻身
django官方文檔
rabbiitMQ官方文檔
django rest framework 官方文檔

1六、最近在研究什麼新技術?

opentack
docker
人工智能API,實現小功能。智能語音
區塊鏈

1七、是否瞭解過領域驅動模型?

相關文章
相關標籤/搜索