整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Web前端培訓:Python與JavaScript

          Web前端培訓:Python與JavaScript — 哪一種最適合Web開發

           JavaScript是一種動態、輕量級的腳本語言,在網頁中占據著中心地位。它編排客戶端腳本,利用其解釋性和面向對象的特性精心制作動態用戶交互。想要了解JavaScript的更多知識,可以參加web前端培訓,以獲得快速提升和進步。

            Python是編程界的后起之秀,在機器學習、網絡開發和軟件測試等應用領域大放異彩。它的普遍吸引力迎合了開發人員和新手。

            Python和JavaScript:Web開發中的前端和后端框架

            讓我們探討一下這些語言在網絡開發的前端和后端中是如何發揮不同作用的。無論你是剛開始還是有一些編程經驗,了解Python和JavaScript都可以為創造獨特的在線體驗打開大門。

            用于后端的Python:

            要開始后端開發之旅,首先要掌握Python本身。了解它的優勢和局限性。然后,深入研究兩個著名的Python框架:Flask和Django。Flask就像一個緊湊版的Python,易于學習和實現——這是一個很好的起點。另一方面,Django雖然更為復雜,但它提供了無與倫比的力量。

            用于前端的Python:

            對于前端Python編程,PyScript脫穎而出。它是一個基于瀏覽器的框架,結合了Python和HTML,簡化了程序構建。PyScript利用現代web技術提供了一個干凈且可擴展的API,使其非常適合制作用戶界面。

            前端JavaScript:

            前端JavaScript框架增強了web應用程序的交互性。流行的選擇包括AngularJS,它豐富了web應用程序的HTML;ReactJS,以可重用的UI組件而聞名;jQuery,一個功能豐富的庫;構建應用程序的主干;Ember,是大網絡項目的理想選擇。加web前端培訓是學習JavaScript很有效的方法,碰到問題能夠及時得到解決,大大提高了學習效率。

            后端JavaScript:

            在后端,JavaScript也大放異彩。像Firebase這樣的框架提供實時數據存儲和同步。Node.js支持構建快速、可擴展的網絡應用程序。PhantomJS提供了可編寫腳本的無頭瀏覽。Express為web應用程序提供了靈活性,而Meteor則支持端到端的JavaScript web開發。

            

            簡而言之:

            Python和JavaScript兼顧前端和后端開發。Python簡單明了的框架使其成為首選。對于初學者來說,Python的Flask提供了一個簡單的入口,而Django提供了高級功能。前端框架增強了JavaScript方面的用戶體驗,而后端框架提供了多種功能。最終,你在JavaScript和Python之間的選擇取決于項目的復雜性和個人偏好。

            Python與JavaScript:速度與性能的對決

            在速度和性能方面,Python和JavaScript占據了中心位置,各自都有獨特的優勢。Python在處理CPU密集型任務方面大放異彩,使其成為復雜計算和處理的可靠選擇。相反,JavaScript通過Node.js提供了多線程功能,為網絡上的動態和實時交互提供了動力。這引發了科技行業關于Node.js與Python后端開發的持續討論。

            Python成為了重數據文件處理、CPU密集型項目和大規模應用程序的最終解決方案。開發人員可以通過使用Cython或NumPy等工具優化Python代碼來提高性能。當我們瀏覽錯綜復雜的web開發時,Python和JavaScript提供了獨特的性能優勢,可以滿足各種項目需求。

            總結

            Python和JavaScript在網絡開發領域站穩了腳跟,各自都有獨特的優勢。當你走上這條編碼之路時,請記住,無論是Python的多功能性還是JavaScript的實時魅力,選擇都會塑造你項目的靈魂。想要掌握Javascript技能和知識,建議參加web前端培訓,課程實時更新,緊跟企業需求,讓你輕松找到工作。

          家好,我是小雨。

          上一講我們介紹的是:Django框架學習筆記(三)Templates模板 ,我們了解了Django中如何加載html頁面、介紹了模板語言DTL、以及靜態文件的加載。現在頁面已經能正常顯示了,我們希望網頁中的鏈接點擊后能跳轉到指定頁面或者自動重定向該怎么做呢?于是我們今天將要介紹url跳轉的知識。與此同時,實際的網站項目為了便于團隊開發各個模塊有各自獨立的app,我們該怎么做讓各個獨立的app正常工作的同時也互不干擾呢?所以今天也會向大家介紹一下Django中的多app環境的管理。

          一、URL跳轉

          URL的跳轉是什么呢?URL的跳轉可以稱為URL重定向,表示從一個HTML頁面跳到另外一個頁面。 URL跳轉有兩種途徑:html的<a>標簽Django的redirect方法

          1. html的標簽跳轉

          把文本或者圖放到a標簽里,點擊a標簽跳轉。在Django中需要注意的是:html里給href的值為指定路徑名而不是整個包含后綴的html文件。

          <li><a href="game/">游戲</a></li>
          <li><a href="movie/">電影</a></li>
          <li><a href="music/">音樂</a></li>

          我們在首頁定義三個超鏈接,分別指向三個頁面

          效果演示:

          通過a標簽訪問指定頁面


          2. 通django跳轉

          滿足一定條件自動跳轉,常使用redirect關鍵字。某些網站如果你沒有登錄的話它會自動跳轉到登錄頁面。

          使用redirect方法進行重定向,首先需要導包:

          from django.shortcuts import redirect

          在views中定義登陸方法時,我們試著從url中獲取用戶名,如果用戶名存在則訪問首頁,如果不存在則重定向至登陸頁面,這個邏輯代碼就可以這樣寫:

          def index(request):
              username = request.GET.get("username")
              if username:
                  return render(request, "index.html")
              else:
                  return redirect("/login/")

          這樣就能實現的功能是:

          用戶想訪問首頁,在沒有登錄的情況下會自動重定向至登錄頁面。但如果系統在url中獲取到用戶名,則打開首頁。

          效果演示:

          用戶沒登錄則訪問登錄頁面,登錄了則訪問主頁


          二、多app項目

          在實際的開發過程中,為了減少相互之間的干擾,以及便于團隊之間的同步開發,網站的每一個模塊都部署在不同的app中。這里我們以B站為例,首頁、電影、音樂分別分布在三個app中,分別是home、movie、music,其結構如下:

          多app環境

          1. 多app環境部署

          首先使用startapp分別創建home、music、movie三個app;接著在settings.pyINSTALLED_APPS列表中將三個app的名稱添加進來。

          INSTALLED_APPS = [
          ... # 這里省略系統默認添加的app名稱
              'home',
              'movie',
              'music',
          ]

          表明這些app現在已經在我們的項目中登記注冊了,否則后期跨app調用的時候會出現問題。

          2. url獨立

          在每一個app文件夾中都獨立設置urls.py文件,系統urls.py通過include關鍵字對各個app下的urls做統一中轉管理。

          我們首先在home下的views中定義一個index方法,使用httpresponse返回字符串“B站首頁”。

          from django.http import HttpResponse
          def index(request):
              return HttpResponse("B站首頁")

          接下來在home下新建一個urls.py,將同級目錄下的views導入進來,定義urlpatterns,將首頁路徑添加進來。

          from django.urls import path
          from . import views
          # ====== home下的url ========urlpatterns = [
              path("", views.index),
          ]

          最后在項目urls.py中做一個中轉,

          from django.urls import path, include
          path('', include("home.urls")),

          這樣就能成功訪問home下的服務了,我們在此基礎上再完成movie和music的配置。它們的views都可以定義自己的index方法,urls訪問對應的index,只要最后在系統項目urls下對各個模塊做好中轉管理即可。

          urlpatterns = [
              path('admin/', admin.site.urls),
              path('', include("home.urls")),
              path('movie/', include("movie.urls")),
              path('music/', include("music.urls")),
          ]

          這樣就能訪問各個模塊下的各個服務了,效果演示如下:

          3. 多app模板文件管理

          在各自的app文件夾下新建一個文件夾templates,記得使用右鍵菜單Mark Directory as Template Folder將文件夾設置為模板文件夾。

          出現問題

          我們在home、movie、music各個app下的模板文件夾里新建html頁面。但是注意如果多個app中有模板文件有重名的話,系統就會只訪問第一個模板文件,我們要杜絕這種情況的發生。

          解決方法:

          在各app下的模板文件夾下再建一個與app同名的文件夾,模板文件就放在這個文件夾里。這樣就可以產生路徑的差異,訪問同名模板文件就不會沖突。

          多app環境下模板文件結構

          我們在views里的render方法把文件夾名加上即可。

          def index(request):
              return render(request, 'home/index.html')

          多app路徑分析過程為:

          • 第一步:當用戶輸入一個url路徑,系統首先到項目urls里找,項目urls里的path方法通過include("app名.urls"),進入對應app文件夾下的urls;
          • 第二步:接著app下的urls會訪問同級文件夾中的views,views里定義了index方法,也就是說會訪問到views里的index方法;
          • 第三步:views里的index方法包含了模板文件的位置,通常為app同名子文件夾/模板文件.html

          以上三步就是多app下url找到模板文件的方法。

          多app環境下url訪問邏輯

          4. 多app靜態文件管理

          多app下訪問靜態文件也是同樣的道理,如果直接訪問同名靜態文件會沖突。我們也是采取同樣的方法在靜態文件夾下再建一個與app同名的子文件夾,來做到路徑的區分。

          多app環境下靜態文件的布置

          注意事項:

          • 項目settings里記得添加靜態文件路徑
          STATICFILES_DIRS = [
              os.path.join(BASE_DIR, 'home', 'static'),
              os.path.join(BASE_DIR, 'movie', 'static'),
              os.path.join(BASE_DIR, 'music', 'static'),
          ]

          讓系統找到每個app下的static文件夾即可。

          • 模板文件html中訪問靜態文件記得加上app同名子文件夾名
          <img src="{% static '/home/img/pic.png' %}">

          效果演示:

          多app環境下分別訪問主頁、音樂、電影頁面


          最后

          以上,我們就完成了url重定向與多app下模板文件與靜態文件的管理。下一節,我們繼續介紹Django相關知識~

          希望能點個贊支持一下~

          非常感謝大家的閱讀!

          什么引入web框架

          web應用的本質

          • 瀏覽器發送一個HTTP請求;
          • 服務器收到請求,生成一個HTML文檔;
          • 服務器把HTML文檔作為HTTP響應的Body發送給瀏覽器;
          • 瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔并顯示;

          涉及的問題

          • 解析http請求
          • 找到對應的處理函數
          • 生成并發送http響應

          web框架工作流程


          ?


          中間件

          • 中間件是請求或者應用開始和結束時注入代碼的機制
          • 常見的web中間件: 鑒權、打印log、session、統計信息、處理數據庫連接 等等

          ?



          golang http 服務端編程

          • golang 的net/http包提供了http編程的相關接口,封裝了內部TCP連接和報文解析的復雜瑣碎的細節
            go c.serve(ctx)最終會啟動goroutine處理請求
          • 使用者只需要和http.request 和 http.ResponseWriter 兩個對象交互就行(也就是一個struct 實現net/http包中的Handler interface中的 ServeHttp方法 )
          //E:\Go\src\net\http\server.go +82 
          type Handler interface {
          	ServeHTTP(ResponseWriter, *Request)
          }
          
          //純 net.http包的server方法
          package main
          
          import (
              "io"
              "net/http"
          )
          
          type helloHandler struct{}
          
          func (h *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
              w.Write([]byte("Hello, world!"))
          }
          
          func main() {
              http.Handle("/", &helloHandler{})
              http.ListenAndServe(":12345", nil)
          }
          
          //////////////////////////////////////////////////////////////////
          
          import (
              "net/http"
          )
          
          type Handle struct{}
          
          func (h Handle) ServeHTTP(response http.ResponseWriter, request *http.Request) {
              switch request.URL.Path {
              case "/info":
                  response.Write([]byte("info"))
              default:
          
              }
          }
          
          func main() {
              http.ListenAndServe(":8888", Handle{})
          }

          • net/http 的另外一個重要的概念 ,ServeMux (多路傳輸):ServeMux 可以注冊多了 URL 和 handler 的對應關系,并自動把請求轉發到對應的 handler 進行處理
          • // 下面看一個帶路由的http server package main import ( "io" "net/http" ) func helloHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello, world!\n") } func echoHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, r.URL.Path) } func main() { mux :=http.NewServeMux() mux.HandleFunc("/hello", helloHandler) mux.HandleFunc("/", echoHandler) http.ListenAndServe(":12345", mux) } // 其實ServeMux 也實現了Handler的ServeHTTP方法所以也是Handler接口 //E:\Go\src\net\http\server.go 2382 func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI=="*" { if r.ProtoAtLeast(1, 1) { w.Header().Set("Connection", "close") } w.WriteHeader(StatusBadRequest) return } h, _ :=mux.Handler(r) h.ServeHTTP(w, r) } // E:\Go\src\net\http\server.go +2219可以看到 net/http包中的 基于map 路由查找 // Find a handler on a handler map given a path string. // Most-specific (longest) pattern wins. func (mux *ServeMux) match(path string) (h Handler, pattern string) { // Check for exact match first. v, ok :=mux.m[path] if ok { return v.h, v.pattern } // Check for longest valid match. var n=0 for k, v :=range mux.m { if !pathMatch(k, path) { continue } if h==nil || len(k) > n { n=len(k) h=v.h pattern=v.pattern } } return }

          golang web框架 GIN golang gin web框架

          //gin框架初始化的流程
          1.初始化engine 
          2.注冊中間件
          3.注冊路由
          
          //響應流程
          1.路由,找到handle
          2.將請求和響應用Context包裝起來供業務代碼使用
          3.依次調用中間件和處理函數
          4.輸出結果
          
          //gin 里面最重要的兩個數據結構
          //1.Context在中間件中傳遞本次請求的各種數據、管理流程,進行響應
          //2.Engine gin 引擎,是框架的實例,它包含多路復用器,中間件和配置設置
          
          
          
          
          // 下面看下open-falcon-api中的實際應用
          //open-falcon-api里面注冊路由和中間件
          //E:\go_path\src\github.com\open-falcon\falcon-plus\modules\api\app\controller\graph\graph_routes.go
          // 首先注冊/api/v1/開頭的path的路由組
          // 然后Use 一個auth的中間件 ,作用是檢查token
          // 這個組后面的所有path 都使用這個中間件 
          // 也就是訪問 /graph/endpoint 時會過 3個中間件(log recovery  auth )+一個EndpointRegexpQuery處理函數
          // 
          func Routes(r *gin.Engine) {
          
          	db=config.Con()
          	authapi :=r.Group("/api/v1")
          	authapi.Use(utils.AuthSessionMidd)
          	authapi.GET("/graph/endpointobj", EndpointObjGet)
          	authapi.GET("/graph/endpoint", EndpointRegexpQuery)
          	authapi.GET("/graph/endpoint_counter", EndpointCounterRegexpQuery)
          	authapi.POST("/graph/history", QueryGraphDrawData)
          	authapi.POST("/graph/lastpoint", QueryGraphLastPoint)
          	authapi.POST("/graph/info", QueryGraphItemPosition)
          	authapi.DELETE("/graph/endpoint", DeleteGraphEndpoint)
          	authapi.DELETE("/graph/counter", DeleteGraphCounter)
          
          	grfanaapi :=r.Group("/api")
          	grfanaapi.GET("/v1/grafana", GrafanaMainQuery)
          	grfanaapi.GET("/v1/grafana/metrics/find", GrafanaMainQuery)
          	grfanaapi.POST("/v1/grafana/render", GrafanaRender)
          	grfanaapi.GET("/v1/grafana/render", GrafanaRender)
          
          }
          
          
          func AuthSessionMidd(c *gin.Context) {
          	auth, err :=h.SessionChecking(c)
          	if !viper.GetBool("skip_auth") {
          		if err !=nil || auth !=true {
          			log.Debugf("error: %v, auth: %v", err, auth)
          			c.Set("auth", auth)
          			h.JSONR(c, http.StatusUnauthorized, err)
          			c.Abort()
          			return
          		}
          	}
          	c.Set("auth", auth)
          }
          
          
          // E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\context.go +715 最后會調用這里的Render方法
          // Render writes the response headers and calls render.Render to render data.
          func (c *Context) Render(code int, r render.Render) {
          	c.Status(code)
          
          	if !bodyAllowedForStatus(code) {
          		r.WriteContentType(c.Writer)
          		c.Writer.WriteHeaderNow()
          		return
          	}
          
          	if err :=r.Render(c.Writer); err !=nil {
          		panic(err)
          	}
          }
          
          // 可以看到這里的bind 是在gin在解析請求payload是否和函數中要求的struct一致
          // E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\context.go +504
          // bind會根據請求中的Content-Type header判斷是json 還是xml
          // 并且根據struct中的tag通過反射解析payload
          
          // Bind checks the Content-Type to select a binding engine automatically,
          // Depending the "Content-Type" header different bindings are used:
          //     "application/json" --> JSON binding
          //     "application/xml"  --> XML binding
          // otherwise --> returns an error.
          // It parses the request's body as JSON if Content-Type=="application/json" using JSON or XML as a JSON input.
          // It decodes the json payload into the struct specified as a pointer.
          // It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid.
          func (c *Context) Bind(obj interface{}) error {
          	b :=binding.Default(c.Request.Method, c.ContentType())
          	return c.MustBindWith(obj, b)
          }
          
          
          type APIEndpointObjGetInputs struct {
          	Endpoints []string `json:"endpoints" form:"endpoints"`
          	Deadline  int64    `json:"deadline" form:"deadline"`
          }
          
          
          func EndpointObjGet(c *gin.Context) {
          	inputs :=APIEndpointObjGetInputs{
          		Deadline: 0,
          	}
          	if err :=c.Bind(&inputs); err !=nil {
          		h.JSONR(c, badstatus, err)
          		return
          	}
          	if len(inputs.Endpoints)==0 {
          		h.JSONR(c, http.StatusBadRequest, "endpoints missing")
          		return
          	}
          
          	var result []m.Endpoint=[]m.Endpoint{}
          	dt :=db.Graph.Table("endpoint").
          		Where("endpoint in (?) and ts >=?", inputs.Endpoints, inputs.Deadline).
          		Scan(&result)
          	if dt.Error !=nil {
          		h.JSONR(c, http.StatusBadRequest, dt.Error)
          		return
          	}
          
          	endpoints :=[]map[string]interface{}{}
          	for _, r :=range result {
          		endpoints=append(endpoints, map[string]interface{}{"id": r.ID, "endpoint": r.Endpoint, "ts": r.Ts})
          	}
          
          	h.JSONR(c, endpoints)
          }
          
          //E:\go_path\src\github.com\open-falcon\falcon-plus\modules\api\main.go  +78
          //初始化gin
          routes :=gin.Default()
          
          //E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\gin.go +148
          // Default returns an Engine instance with the Logger and Recovery middleware already attached.
          func Default() *Engine {
          	debugPrintWARNINGDefault()
          	engine :=New()
          	engine.Use(Logger(), Recovery())
          	return engine
          }
          
          //E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\gin.go +119 
          // new方法 返回一個不帶中間件的 單例engine ,并且把context 放在池中
          func New() *Engine {
          	debugPrintWARNINGNew()
          	engine :=&Engine{
          		RouterGroup: RouterGroup{
          			Handlers: nil,
          			basePath: "/",
          			root:     true,
          		},
          		FuncMap:                template.FuncMap{},
          		RedirectTrailingSlash:  true,
          		RedirectFixedPath:      false,
          		HandleMethodNotAllowed: false,
          		ForwardedByClientIP:    true,
          		AppEngine:              defaultAppEngine,
          		UseRawPath:             false,
          		UnescapePathValues:     true,
          		MaxMultipartMemory:     defaultMultipartMemory,
          		trees:                  make(methodTrees, 0, 9),
          		delims:                 render.Delims{Left: "{{", Right: "}}"},
          		secureJsonPrefix:       "while(1);",
          	}
          	engine.RouterGroup.engine=engine
          	engine.pool.New=func() interface{} {
          		return engine.allocateContext()
          	}
          	return engine
          }
          
          
          //E:\go_path\src\github.com\open-falcon\falcon-plus\modules\api\app\controller\routes.go
          //r.Run(port) 最后調用的是  net.http.ListenAndServe
          func (engine *Engine) Run(addr ...string) (err error) {
          	defer func() { debugPrintError(err) }()
          
          	address :=resolveAddress(addr)
          	debugPrint("Listening and serving HTTP on %s\n", address)
          	err=http.ListenAndServe(address, engine)
          	return
          }
          
          
          
          
          //E:\Go\src\net\http\server.go +2686
          func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
          	handler :=sh.srv.Handler
          	if handler==nil {
          		handler=DefaultServeMux
          	}
          	if req.RequestURI=="*" && req.Method=="OPTIONS" {
          		handler=globalOptionsHandler{}
          	}
          	handler.ServeHTTP(rw, req)
          }
          
          //E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\gin.go +321
          //我們可以看到 在gin中實現了ServeHTTP方法  net.http.Handler
          
          // ServeHTTP conforms to the http.Handler interface. 
          // 這里使用sync.pool cache context數據結構,避免頻繁GC,每次使用都初始化
          //一個struct實現了 interface中的方法 就說明這個struct是這個類型
          func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
          	c :=engine.pool.Get().(*Context)
          	c.writermem.reset(w)
          	c.Request=req
          	c.reset()
          
          	engine.handleHTTPRequest(c)
              
          	engine.pool.Put(c)
          }
          
          
          
          // gin 里面處理請求的核心方法
          // 根據一些配置去 壓縮前綴樹 radix.tree中找到對應的handleChain 然后執行
          // 注意這句handlers, params, tsr :=root.getValue(path, c.Params, unescape)
          // 路由查找的過程是 從基數樹的根節點一直匹配到和請求一致的節點找到對應的handlerchain
          // 注冊路由 E:\go_path\src\github.com\open-falcon\falcon-plus\vendor\github.com\gin-gonic\gin\gin.go +243 
          // 從下面的addRoute方法中可以看到gin 為每個HttpMethod  GET POST PUT DELETE都注冊了一顆tree
          // 并且有priority 即最長的路徑優先匹配
          /*
          func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
          	assert1(path[0]=='/', "path must begin with '/'")
          	assert1(method !="", "HTTP method can not be empty")
          	assert1(len(handlers) > 0, "there must be at least one handler")
          
          	debugPrintRoute(method, path, handlers)
          	root :=engine.trees.get(method)
          	if root==nil {
          		root=new(node)
          		engine.trees=append(engine.trees, methodTree{method: method, root: root})
          	}
          	root.addRoute(path, handlers)
          }
          */
          
          
          func (engine *Engine) handleHTTPRequest(c *Context) {
          	httpMethod :=c.Request.Method
          	path :=c.Request.URL.Path
          	unescape :=false
          	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
          		path=c.Request.URL.RawPath
          		unescape=engine.UnescapePathValues
          	}
          
          	// Find root of the tree for the given HTTP method
          	t :=engine.trees
          	for i, tl :=0, len(t); i < tl; i++ {
          		if t[i].method !=httpMethod {
          			continue
          		}
          		root :=t[i].root
          		// Find route in tree
          		handlers, params, tsr :=root.getValue(path, c.Params, unescape)
          		if handlers !=nil {
          			c.handlers=handlers
          			c.Params=params
          			c.Next()
          			c.writermem.WriteHeaderNow()
          			return
          		}
          		if httpMethod !="CONNECT" && path !="/" {
          			if tsr && engine.RedirectTrailingSlash {
          				redirectTrailingSlash(c)
          				return
          			}
          			if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) {
          				return
          			}
          		}
          		break
          	}
          
          	if engine.HandleMethodNotAllowed {
          		for _, tree :=range engine.trees {
          			if tree.method==httpMethod {
          				continue
          			}
          			if handlers, _, _ :=tree.root.getValue(path, nil, unescape); handlers !=nil {
          				c.handlers=engine.allNoMethod
          				serveError(c, http.StatusMethodNotAllowed, default405Body)
          				return
          			}
          		}
          	}
          	c.handlers=engine.allNoRoute
          	serveError(c, http.StatusNotFound, default404Body)
          }
          
          
          
          


          python django (django框架復雜,先簡單看一下)


          主站蜘蛛池模板: 日本免费电影一区| 亚洲一区爱区精品无码| AV天堂午夜精品一区| 亚洲视频一区二区三区| 国产一区二区三区内射高清| 精品欧洲av无码一区二区14| 精品国产日产一区二区三区| 精品国产一区二区22| 免费萌白酱国产一区二区| 亚洲Av永久无码精品一区二区| 无码精品人妻一区二区三区免费看| 久久精品一区二区三区中文字幕 | 在线精品动漫一区二区无广告| 精品亚洲av无码一区二区柚蜜| 亚洲美女视频一区| 国模吧一区二区三区| 国精产品一区一区三区| 亚洲日本中文字幕一区二区三区 | 视频精品一区二区三区| 一区二区三区在线|欧| 国产伦理一区二区| 无码人妻精品一区二区| 人妻无码视频一区二区三区| 夜夜添无码一区二区三区| 精品久久一区二区三区| 色偷偷av一区二区三区| 午夜福利一区二区三区在线观看| 夜夜嗨AV一区二区三区| 一区二区三区四区免费视频 | 国产精品亚洲一区二区在线观看| 无码人妻精品一区二区蜜桃 | 国产人妖视频一区二区破除 | 亚洲一区二区三区电影| 无码人妻精品一区二区在线视频 | 一区二区三区高清在线| 中文字幕在线无码一区二区三区| 精品日产一区二区三区手机| 亚洲一区二区三区免费视频| 精品国产一区二区三区AV | 精品国产亚洲一区二区在线观看 | 国产一区二区三区内射高清|