2012年8月27日 星期一

區別 Django 中的 STATIC_ROOT 與 STATICFILES_DIRS

 

看此篇文章之前,可以先參考

深入了解 django 的 static 設定

 

本文開始

在寫 django 時,我們會引用許多的 app,也會自行製作許多的 app,每一個 app 都可能有自己的 static 檔案或資料夾。

只要在 INSTALLED_APPS 裡引用的 app,便會成為 python manage.py collectstatic 的收集對象,而收集後存放的路徑,便是 STATIC_ROOT

這麼一來便可以讓 app 有自己的 static 資料夾,不需要混在一起了,維護上也會簡單許多。

django default settings.py 裡面 STATIC_ROOT 的上方,也特別警告我們不應該手動更改 STATIC_ROOT 裡面的檔案。

 

有兩個情況我們需要設置 STATICFILES_DIRS

  1. 專案需要一個 static 檔案或資料夾,但卻不知該如何歸類在哪一個 app 底下。
  2. 專案需要改寫某個引用 app 底下的 static 檔案,但卻不希望動到原本 app 底下的 static 檔案。

狀況一我們有待商榷,畢竟「不知該如何歸類」不應該出現在一個成熟的專案下;而狀況二卻很容易發生。

此時便需要設置 STATICFILES_DIRS,越上方的設置優先權越高,而 STATICFILES_DIRS 的優先權當然也高於 INSTALLED_APPS 內的 app

(INSTALLED_APPS 本身也遵循越上方的 app 優先權越高的原則)

admin 舉例

我若要改寫 django/contrib/admin/static/admin/css/base.css,那麼便可如此指定

STATICFILES_DIRS = (
'/project/mystatic',
)

然後建立 /project/mystatic/admin/css/base.css 檔案後編輯,而後下達

python manage.py collectstatic

 

便會將 /project/mystatic/admin/css/base.css 收集到 STATIC_ROOTadmin/css/base.css 底下,並依照優先權決定覆蓋

2012年8月26日 星期日

深入了解 django 的 static 與 media

 

為什麼要設定 static?

為什麼一但設置在 apache 中,static 設定就變得格外重要?開發時,使用 runserver 都不用管這些設定也可以正常運作!

其實那是因為 runserver 是用程式動態決定檔案位置的,如此一來這些 static 檔案,便是參照各「套件」底下的 static 資料夾,而不需要另外設置

作怪的地方在下方,註解起來 runserver 就無法「使用」各套件底下的 static 了(反之應該也可以修改成在 apache 中使用各套件底下的 static,未測試過,也不推薦)

django/contrib/staticfiles/management/commands/runserver.py

image

 

但是為何不能使用 runserver 在正式環境呢?

官方也有提到

https://docs.djangoproject.com/en/dev/ref/django-admin/#runserver-port-or-address-port

DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through security audits or performance tests. (And that's how it's gonna stay. We're in the business of making Web frameworks, not Web servers, so improving this server to be able to handle a production environment is outside the scope of Django.)

 

static 的檔案,讓 django 動態處理,累積起來也是十分浪費效能的,我猜這也是原因之一

 

static 設置說明

在寫 Web 時的路徑非常重要,所以往往因為專案路徑改變而發生悲劇,在 Django 裡,你必須了解以下兩種設置有何不同。(media 觀念亦同)


STATIC_URL = "/static/"

這指的是你的 Template 在撰寫 html 時,所引用的路徑,與 Web Server (如 apache) 的指向息息相關。

所有 Django developer 在撰寫 Template 都會遵守的寫法

<script src="{{ STATIC_URL }}mezzanine/js/jquery.tools.js"></script>

or

<link rel="stylesheet"
type="text/css"
href="{% static "admin/css/login.css" %}" />


PS:兩種寫法在意義上似乎有所不同,有機會研究再發佈一篇文章

 

所以如果使用 apache,那麼上面的設置便會全部指向

[ApacheDocumentRoot]/static/

(如 C:/AppServ/www/static)

 

STATIC_ROOT = "C:/AppServ/www/static/"

這個設置是為了讓 python manage.py collectstatic 知道將 static 檔案收集在哪。

原則上必須與 STATIC_URL 指向的路徑一致,才不會導致與 Web Server 找到的檔案不同

在這個 case 中,就會等於 C:/AppServ/www/static

 

PS:在 apache 的 conf 中,也可以利用 Alias 來轉向,只要設置正確就好

 

STATIC_ROOT 更詳細的說明,可以參考

區別 Django 中的 STATIC_ROOT 與 STATICFILES_DIRS

 

說了這麼多 static,那 media 呢?

mediastatic 不同的地方在於,media 通常是用於放置使用者可新增、編輯、刪除的資料,如上傳的圖片,文件等,除此之外,其餘觀念與 static 的設置沒有什麼不同

Java Applet 在 Client 權限全開的方法

如同 Flash(Flex)、Silverlight…etc在 Client 端執行的程式,Java Applet 在安全性上也有許多限制,原則上只要會占用本地端資源的行為(如開啟socket,存取檔案...等),都是會被拒絕的。

因此必須經過幾個步驟:

  1. 將 Java Applet 程式打包為 jar 檔
  2. 利用 keytool 產生 keystore
  3. 接著再利用 keytool 與此 keystore 產生證書
  4. 最後用 jarsigner 幫 jar 檔加上簽名

 

keytool -genkey -keystore bmcool.store -alias bmcool

keytool -export -keystore bmcool.store -alias bmcool -file bmcool.cert

jarsigner -keystore bmcool.store AppletPolicy.jar bmcool

解決 The _imaging C module is not installed

 

為了搞這個,花了我半天的時間來研究...

在專案中,有一個功能會利用到 PIL 來做縮圖,而 Server 總是回應我

The _imaging C module is not installed

 

但是在 runserver 環境下,都沒有此問題,找了半天,原來是因為官方的 PILmod_wsgi 並不相容。(似乎編譯時連結的函式庫不同,所以無法共用?)

 

最後其實只要把官方的 PIL 移除,改裝這個非官方的 PIL 就可以運作了…

http://www.lfd.uci.edu/~gohlke/pythonlibs/

 

Reference


與本文無關的抱怨

會研究這麼久,是想說應急把 runserver 註冊到 windows service 裡面,結果

  • 要嘛無法進行 Log (使用 os.system 指令)
  • 要嘛無法中斷 (使用 subprocess.Popen 指令)

其實花最多時間研究的,是 subprocess.Popen 如何在 windows 環境下把子程序中斷掉...無法中斷當然也就無法採用這個 solution

以下是程式碼,如果有大德知道如何中斷,麻煩分享分享...


import os
import sys

import win32serviceutil

import subprocess
import time

class service(win32serviceutil.ServiceFramework):
_svc_name_ = 'Django'
_svc_display_name_ = 'Django'
_svc_description_ = 'Django'

def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.isAlive = True

def SvcStop(self):
self.isAlive = False

def SvcDoRun(self):
self.timeout = 1000

timestamp = time.localtime()
now = time.strftime("%Y%m%d%H%M%S", timestamp)

outpath = 'C:/AppServ/www/demo/' + now + 'stdout.txt'
errpath = 'C:/AppServ/www/demo/' + now + 'stderr.txt'

with open(outpath, 'wb', 0) as out:
with open(errpath, 'wb', 0) as err:
sub = subprocess.Popen('python C:/AppServ/www/demo/manage.py runserver 0.0.0.0:800', stdout=out, stderr=err)

while True:
if not self.isAlive:
# kill sub here
break

if __name__ == '__main__':
win32serviceutil.HandleCommandLine(service)

在 Windows Service 中註冊 Python Script

 

將自己寫的程式註冊在 Windows Service 中有幾個好處:

  1. 可以在系統啟動時自動啟動。
  2. 可設定程式出了狀況之後的處理機制。(如馬上重啟…etc)
  3. 在多人連線的環境下,常常會限制「登入個數」,也會設定「閒置登出時間」,一但執行程式的 Session 被登出,程式就停止了。

程式碼如下:

service.py


import win32serviceutil

class service(win32serviceutil.ServiceFramework):
_svc_name_ = "ServiceName"
_svc_display_name_ = "Service display name"
_svc_description_ = "Service description"

def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.isAlive = True

def SvcStop(self):
self.isAlive = False

def SvcDoRun(self):
self.timeout = 1000
while self.isAlive:
# your script here

if __name__ == '__main__':
win32serviceutil.HandleCommandLine(service)

 

接著只要在命令提示字元下達

python service.py install

 

就可以註冊一個服務到windows裡了

 

其他指令可以下達此命令查詢

python service.py

2012年8月24日 星期五

MySQL 匯入與匯出

 

Quick Note

匯出

mysqldump -u username -p database > backup.sql

 

匯入

mysql -u username -p database < backup.sql

取得 Python 在系統中 Library 的路徑

 

Quick Note:

 

In python

from distutils.sysconfig import get_python_lib
print(get_python_lib())

or

In os shell

python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"