Windows+Apache+Python+Django 踩坑記錄


摘要

  使用Python進行Web項目開發;相對於主流三大Web端解決方案(Java/.NET/PHP) Python在某些方面具有一定的優勢,相對 Java/.NET 有更輕量級的部署方案,相對PHP有更安全開放的環境支持,這些不同點幾乎完全取決於Python語言本身的特性。

0x01: 環境部署

  注:開發環境與運行環境的部署需要的基本技能 —— 理論基礎知識扎實,了解相關基本原理,了解具體開發體系;如果不具備這些能力那么遇到問題就會很懵

  0x11: Windows+Apache 部署

  1. Apache壓縮包直接百度 "Apache" 就能找到官網下載了,飛機票>> Apache24 ;壓縮包解壓至安裝目錄,路徑最好不要含有中文和空格(江湖規矩)

  2. httpd.conf 配置文件(apachePath/conf/httpd.conf),Apache部署中最重要的部分,一般只用修改第一條 ServerRoot 就可以了,文檔中 "#" 為行注釋

    ServerRoot 改為你的真實路徑(一般在37行上下),Ex: ServerRoot "D:/Program/Apache/Apache24",新版本Apache中采用 "SRVROOT" 宏替換后面所有會用到路徑的地方,新版本修改 Define SRVROOT "c:/Apache24" 為真實路徑可全局替換,較老版本要手動修改以下兩個地方:標識靜態文件路徑(大概在251行上下)以及文件訪問權限,CGI 腳本路徑及訪問權限(大概在368/380行上下);注意:路徑分隔為 "/" 而不是 "\"

    Listen 為監聽端口,默認80(通常在60行上下)一般不用修改

    LoadModule 為隨Apache啟動加載的模塊(71-185左右),一般不用管

    ServerName 取消注釋(225上下),好像是 IANA DNS導航什么的

    DocumentRoot 表示靜態文件路徑,見第一條 ServerRoot

    ErrorLog 表示記錄文件輸出路徑(300行上下),debug的時候會經常用到這個文件,不更改記錄級別的話提示警告什么的也在里面,我也不知道咋回事兒

    LogLevel 表示記錄輸出級別(310行上下),取值文檔中有注釋麻煩自己看

    Include 表示要引入的其它配置文件(原文檔中490-530行大量出現),要使用了再詳細了解吧

    <Files xx.xx*> 表示文件訪問權限,按類型限制

    <IfModule xxx_module> 標簽表示如果加載了 xxx_module 模塊就將其內容作為該模塊的配置

    <Directory xxxx> 標簽表示文件夾權限,見第一條 ServerRoot

   3. 安裝/卸載系統服務,不安裝沒法用

    安裝:管理員權限打開控制台,cd 到 Apache24/bin/ 目錄下,執行 "httpd -k install" 將Apache服務注入系統,可使用 -n 參數指定服務名(一般不要這么干),Ex: "httpd -k install -n "Apache2439" ",如此步安裝過程報錯考慮可能是VC庫版本問題,一般Apache壓縮包中會有一個空文件,文件名表示該版本所依賴的VC庫,若無請自行下載

    安裝完成后可到系統服務將該服務 "自動啟動" 改為手動啟動,否則該服務將隨系統開啟而啟動;如果部署到服務器則不用修改

    卸載:管理員權限打開控制台,cd 到 Apache24/bin/ 目錄下,執行 "httpd -k uninstall" 卸載服務,若注入服務時使用 -n 參數指定服務名則此處也要用 -n 參數指定

  4. 啟動/停止/重啟服務

    啟動:管理員權限打開控制台,cd 到 Apache24/bin/ 目錄下,執行 "httpd -k start" 開始運行服務器,若注入服務時使用 -n 參數指定服務名則此處也要用 -n 參數指定

    重啟:"httpd -k restart"

    停止:"httpd -k stop"

    其它:"httpd -h" 可查看httpd支持的所有命令,當然,是英文版的

  n. 若上述步驟都沒有什么問題,則訪問 127.0.0.1 就能看到 "It works!" 了(服務器需允許httpd.exe通過防火牆)

  0x21: Apache+Django部署

  注:Python安裝都不會的就不用繼續看了

  1. 運行模式解釋,Apache服務器腳本運行模式有一大堆,具體是咋回事兒我也不是很懂,以下是我對其中一部分的個人理解,若有偏差歡迎指正

    CGI: 服務器收到請求后由配置信息找到CGI程序(腳本)路徑,隨后由該程序指定的運行方式運行(直接運行或解析器),然后將執行結果返回給服務器調用處

    FCGI: GCI的升級版,改進CGI每次服務器的請求都會調用一次CGI程序體浪費空間和性能的缺點;FCGI創建一個程序執行的管理程序,服務器只與管理程序通信(通信機制一般使用socket)。每次請求會被FGCI管理程序分配給工作進程或線程,由於管理進程事先會啟動多個工作進程/線程,所以省去了事務生成/銷毀的系統開銷

    WSGI: FCGI的改進版,管理程序實現方式改為服務器插件而不是使用socket通信,官方文檔中一般使用 Middleware(中間件) 這個概念,可避免端口占用,主要性能提升在於降低通信開銷(內存共享快於socket通信)

  2. 中間件 mod_wsgi 是Django在Apache上的一種方案,采用上述WSGI的實現方式

  3. Django安裝,建議直接 "pip install django" 安裝,安裝完成后會有 "Success" 之類的提示,可執行 "pip list" 可查看安裝包列表內是否有 "Django x.x.x" 以確認安裝

    3.1 pip安裝緩慢原因:下載源在國外,解決:修改下載源,方法:"C:/Users/用戶名" 目錄下創建 "pip" 文件夾,文件夾內創建 "pip.ini" 配置文件,內容為:

      [global]

      index-url = https://pypi.douban.com/simple/

    3.5. Django中一些基礎概念的介紹

      項目:一個Web項目的容器,其中包括該Web項目要用到的所有文件,例如靜態文件、Python腳本、數據庫等

      應用:Web項目中的一個功能的所有實現,代碼以及數據

      項目和應用是多對多的關系,一個項目可由多個應用構成,一個應用可供多個項目使用

  4. mod_wsgi 安裝,去Python庫里下載mod_wsgi,模塊版本一定要對應Apache和Python的版本,因為這是一個中間件,就是用來適配兩端模塊的,再送一張飛機票>> mod_wsgi ,下載到的是 whl 文件,使用 "pip install mod_wsgi-xxx.whl" 進行安裝

  5. 創建Django項目/應用

    控制台執行 "django-admin startproject projName" ,生成一個Django項目,同上 django-admin 也在Python 中 Scripts 目錄下,該命令會在指定目錄生成一個Django項目文件結構,不指定目錄則生成在當前目錄,使用 "django-admin startapp appName" 生成一個應用,貼出自用的一個生成項目和應用的 .bat 腳本

@echo off
echo.  ** Django **
echo.新建 Django 項目輸入 1
echo.新建 Django 應用輸入 2
set /p cho=輸入后回車: 
goto tag%cho%
:tag1
set /p projName=輸入項目名: 
django-admin startproject %projName%
goto end
:tag2
set /p appName=輸入應用名: 
django-admin startapp %appName%
:end
echo.請自查當前目錄是否生成文件
pause
newDjango.bat

  

  6. Apache 適配 mod_wsgi 中間件,修改配置文件 httpd.conf

    注:網上一堆找 xxx.so 模塊文件再改上述 httpd.conf 中 LoadModule 是不可行的,因為Python3之后的版本使用的模塊為 pyd 格式

    控制台執行 "mod_wsgi-express module-config" ,該命令中的 mod_wsgi-express 在 Python 目錄中 Scripts 文件夾下,如果環境變量 Path 中沒有該 Scripts 的路徑就 cd 過去再用,將得到的3行結果復制下來,粘貼到 Apache 中的 httpd.conf 配置文件末尾,一般是 LoadFile+LoadModule+WSGIPythonHome,分別表示Python解析器路徑/中間件路徑/Python容器路徑(也可執行 "mod_wsgi-express module-config >> ApachePath/conf/httpd.conf",ApachePath代表Apache安裝根目錄,如果你熟悉命令行應該知道這是個啥)

    添加行 " WSGIScriptAlias / "djangoPath/djangoName/wsgi.py" ",該行為Apache找到Django項目提供依據,路徑為Django項目下的 wsgi.py 文件

    添加行 " WSGIPythonPath "djangoPath" ",該行為Django項目的容器路徑

    配置 wsgi.py 的訪問權限:

      <Directory "djangoPath/djangoName">

       <Files "wsgi.py">
        Require all granted
       </Files>
      </Directory>

    配置靜態文件路徑及訪問權限:

      Alias /static "djangoPath/static"

      <Directory "djangoPath/static">
       AllowOverride None
       Options None
       Require all granted
      </Directory>

    配置多媒體文件路徑及訪問權限:(可選)

      Alias /media "djangoPath/media"

      <Directory "djangoPath/media">
       AllowOverride None
       Options None
       Require all granted
      </Directory>

    我的配置代碼

#配置wsgi.py訪問權限
WSGIScriptAlias / "D:/Program/Apache/Apache24/htdocs/dj/dj/wsgi.py"
WSGIPythonPath "D:/Program/Apache/Apache24/htdocs/dj"
<Directory "D:/Program/Apache/Apache24/htdocs/dj/dj">
<Files "wsgi.py">
Require all granted
</Files>
</Directory>

#此項為靜態文件路徑
Alias /static "D:/Program/Apache/Apache24/htdocs/dj/static"
#靜態路徑權限配置
<Directory "D:/Program/Apache/Apache24/htdocs/dj/static">
AllowOverride None  
Options None  
Require all granted
</Directory>

#此項為多媒體文件路徑
Alias /media "D:/Program/Apache/Apache24/htdocs/dj/media"
#多媒體權限配置
<Directory "D:/Program/Apache/Apache24/htdocs/dj/media">
AllowOverride None  
Options None  
Require all granted
</Directory>
httpd.conf

  n. 配置完成以上內容重啟Apache,使用瀏覽器訪問 127.0.0.1 就能看到Django的歡迎界面了(服務器需要在Django項目中setting.py中設置 "ALLOWED_HOSTS=['*']",詳見Django配置文件解析)

0x02: 使用Django進行開發(Python3.7+Django2.2.2)

  0x12: Django框架簡介

  1. MVT,應該屬於設計模式什么的吧,其實思想和MVC差不多

    M(Model): 數據持久層,操作數據庫的

    V(View): 視圖層,其實是控制邏輯的

    T(Template): 模板層,返回給用戶看的內容

  2. 最小文件結構,執行 "django-admin startproject projName" 生成

  projName

   |-- projName<DIR>

   |--  |--  __pycahce__<DIR> #首次運行后自動生成的Python二進制文件

   |--   |--  ....pyc

   |--  |--  __init__.py #空文件,Python模塊標識

   |--  |--  setting.py #該項目的配置信息

   |--  |--  urls.py #該項目的所有URL路由

   |--  |--  wsgi.py #WSGI的接口??

   |-- db.selite3 #項目首次運行后自動生成的數據庫文件(若未修改Django默認使用的數據庫SQLite3)

   |-- manage.py #管理該項目的文件

  3. 擴展文件結構,自行創建(可選)的文件結構

    projName/templates<DIR>: 放置html文件的路徑,Django中成為模板文件

    projName/static<DIR>: 放置靜態文件,包括css/js/image

    projName/media<DIR>: 放置多媒體文件,大概除了上面兩個其它的文件都可以放這兒吧,也不是很懂這是干嘛的

    projName/projName/views.py: 視圖文件,其實名字隨便取,但最好這樣(江湖規矩)

    projName/projName/models.py: 模型文件,用來編寫模型的,只能是這個名字好像

  0x22: 項目配置,setting.py

    BASE_DIR: 項目所在路徑,不常改

    SECRET_KEY: 啥密鑰來着??不常改

    DEBUG: 調試模式默認為True,用於輸出調試信息,項目上線后應改為False

    ALLOWED_HOSTS: 允許通過的地址,上線后一般設置為['*']

    INSTALLED_APPS: 安裝的應用,創建應用后需要在此添加

    MIDDLEWARE: Django提供的工具集,如CSRF

    ROOT_URLCONF: url配置文件,指向項目下的urls.py路由文件,一般不改

    TEMPLATES: 模板配置文件

    WSGI_APPLICATION: CGI應用實例,一般不改

    DATABASES: 數據庫配置

    AUTH_PASSWORD_VALIDATORS: 密碼認證配置,一般不改

    # 以下為國際化配置

    LANGUAGE_CODE: 語言('zh-hans'),設置為中文后Django主頁顯示為中文

    TIME_ZONE: 時區('Asia/Shanghai')

    USE_I18N: 國際化

    USE_I10N: 國際化

    USE_TZ: 時間存儲帶時區(False)

    STATIC_URL: 靜態文件(CSS/JS/Image/Fonts)位置('/static/')

    # 以下為非默認配置

    APPEND_SLASH: 自動在url后加 '/', 默認為True

    STATICFILES_DIRS: 靜態文件路徑,設置為 (os.path.join(BASE_DIR, 'static'),) 否則使用Django自帶服務器啟動時不能訪問靜態文件

  0x32: 其它常用操作

  1. 數據遷移,數據庫生成與更改后都應執行數據遷移指令,控制台執行以下命令

    python manage.py makemigrations #創建數據庫文件夾migrations(存在則跳過)

    python manage.py migrate #生成數據表及填充權限

    創建管理員用戶,用於登錄Django的控制台 127.0.0.1/admin

      python manage.py createsuperuser #創建管理員,然后輸入一堆信息就成了

  2. 新應用目錄結構,略

  3. 啟動Django自帶的Web調試服務器,只能用作調試,並發性為0

    控制台cd到Django項目根目錄下,執行 "python manage.py runserver",Django會在127.0.0.1:8000開啟服務器,runserver 可選參數為[ip:port]

  4. 新增應用后,應在 setting.py 文件中的 INSTALLED_APPS 中添加該應用的名稱

  5. 使用MySQL數據庫,大概記錄一下(我使用的默認的sqlite,沒有用MySQL)

    MySQL數據庫安裝,請自行百度

    Python MySQL連接驅動安裝,老規矩 "pip install pymysql"

    項目中使用MySQL數據庫需要在 __init__.py 中初始化數據庫,代碼為:

      import pymysql

      pymysql.install_as_MySQLdb()

    修改項目 setting.py 文件數據庫部分:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', #Django中Model的實現
        'NAME': 'dbName', #數據庫名稱
        'USER': 'loginUserName', #登錄用戶
        'PASSWORD': 'loginPwd', #登錄密碼
        'HOST': '127.0.0.1', #數據庫位置
        'PORT': '3306', #數據庫監聽端口
    }
}
DATABASES

  6. setting.py 模板路徑設置,TEMPLATES 中 'DIRS':[BASE_DIR+'/templates',]

  7. Django后台管理工具,以下只做簡要介紹,其它請自行查找

    訪問 127.0.0.1/admin進入管理頁面(未登錄顯示登錄)

    服務器部署 頁面沒有css樣式原因:未作 admin 靜態文件遷移(Apache配置文件中將權限交給Django后沒有決定路徑解析的權限),解決:將 "PythonPath/Lib/site-packages/django/contrib/admin/static" 目錄下的 "admin" 目錄拷至 "ApachePath/htdocs/djangoName/static" 文件夾下

  8. Ajax禁止問題,報錯為 "CSRF token missing or incorrect.",原因:CSRF阻止,解決:注釋掉配置文件 setting.py 中 "MIDDLEWARE" 中的 csrf 插件

  0x42: 開發部分

  1. 核心部分概述

    urls.py: Django中的路由系統,說明網址與視圖層(函數調用)的映射關系

    views.py: Django中的視圖層,其中放置的函數供路由系統調用

    models.py: Django中的模型層,供視圖層調用,用於處理數據持久化,屏蔽相對底層的操作(直接操作SQL語句),當然Django也提供直接執行SQL語句的接口,但不建議你這么干

  2. urls.py, views.py, models.py

###########urls.py###########
# 當 "urlpatterns" 條目為空或只存在 admin 映射時訪問 127.0.0.1 會映射到Django默認主頁

from django.contrib import admin
from django.urls import path
from . import views #存在 views.py 文件時可導入視圖文件以使用其中的函數

urlpatterns = [
    path('admin/', admin.site.urls), #將.../admin映射到Django管理界面
    path('sayHello/', views.sayHello), #調用 sayHello 視圖
]

###########views.py###########
# 使用 "django-admin startapp appName" 創建的應用自動生成該文件

from django.shortcuts import render,HttpResponse,redirect #通常使用這3種方式返回
from . import models #如需使用則手動建立該文件

def sayHello(request):
    return HttpResponse('Hello Django.')

###########models.py###########
#使用 "django-admin startapp appName" 創建的應用自動生成該文件
#修改本文件中內容后執行數據遷移指令,自動生成數據庫結構映射

from django.db import models

# 模型建立示例
class User(models.Model):
    name=models.CharField(primary_key=True,max_length=16)
    age=models.IntegerField(default=0)
View Code

    編寫完成后重啟服務器,訪問 127.0.0.1:8000/sayHello 就能看到結果了

  3. 一個使用模板+靜態資源的示例setting.py 中需配置 STATICFILES_DIRS 的值

    文件結構

   projName

    |--  projName<DIR>

     |--  __init__.py

     |--  settings.py

     |--  urls.py

     |--  views.py

     |--  wsgi.py

    |--  static<DIR>

     |--  templateTest.css

     |--  templateTest.jpg

     |--  templateTest.js

    |--  templates<DIR>

     |--  templateTest

    |--  manage.py

##################urls.py##################
from django.urls import path
from . import views

urlpatterns = [
    path('<int:pageNum>/',views.template),
]

##################views.py##################
from django.shortcuts import render

def template(request,pageNum):
    content={
        'pageNum':pageNum,
    }
    return render(request,'templateTest.html',content)

##################templateTest.html##################
<!DOCTYPE html>
<html>
<head>
    <title>testPage</title>
    <link rel="stylesheet" type="text/css" href="../static/templateTest.css">
</head>
<body>
    <p>圖片顯示為圓形則css/圖片加載成功</p>
    <p>彈出對話框則javascript腳本加載成功</p>
    <p>括號內為地址欄輸入的數字({{pageNum}})</p>
    <img src="../static/templateTest.jpg">
    <script type="text/javascript" src="../static/templateTest.js"></script>
</body>
</html>

##################templateTest.css##################
img{
    width: 200px;
    height: 200px;
    border-radius: 50%;
}

##################templateTest.js##################
document.onload=alert('調用javascript');
View Code

0x03: 后記

  寫得有點久了,95%是在做東西的時候寫的,到發布的時候已經快一個月時間了,其中有些東西現在也記不大清了;當時沒有發布我覺得可能有些重要的地方沒寫完,發布之前我又重新把上面的東西都跑了一次,發現果然是有些東西沒寫到 0.0

  這篇文章可能不是描述的最詳細的,但應該是這一套技術比較全面的了,如果有什么問題或建議請回復評論(雖然最后確實頭都寫暈了 555~)

  原創文章,轉發請注明

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM