django-grid

django 裡面怎麼好像沒有內建的 grid 產生器? 沒有在 admin app 裡找,後來是找到這個 django-grid ,看起來用法很簡單,就用了。一開始是照著用,然後還去改了他原來的 template,後來才想到應該在自己要用到 grid 的 template 裡用 {% include ‘grid/object_list.html’ %} 才對,這樣就可以不用更動到原來的 template。

grid 裡已經有處理分頁的部分,官方的文件沒提到的幾點:

  1. 自訂 column 的標題:如果你的 model 裡已經有加上去的話,它會自動去抓,但是如果是自訂的欄位,就要這樣用:columns = ( (‘field1’, ‘欄位1’), (‘field2’, ‘欄位2’), )
  2. 刪除:grid 有定義這個,在定義 columns 的時候,要使用 __delete__,例如: columns = ( (‘field1’, ‘欄位1’), (‘field2’, ‘欄位2’), (‘__delete__’, ‘刪除’), )
  3. 自行定義欄位:要額外增加 custom_columns,其形態是 dict,grid 在遇到裡面指定的元素時,會改用你定義的 template 去顯示,來達到自定義的效果:custom_columns={ ‘field1’: ‘app/custom_field1.html’ }
  4. l10n:grid 沒有做這部分,這就要自己去改 template 了。

總結範例:[python]from grid import Grid
class MyGrid(grid):
model = your_model
columns = ( (‘field1’, ‘欄位1’), (‘field2’, ‘欄位2’), )
sortable = (‘field1’,)
custom_columns={ ‘field1’: ‘app/custom_field1.html’ }
[/python]

gedit plugin

因為想把一些文字處理動作集中一次用 python 來處理,然後處理完還要可以手動編輯,就想到 gedit 可以自訂 plugin,之前也沒試過,就試試看。

一開始我是找到 gedit 3 的 plugin howto ,看到一半發現 plugin 路徑怪怪的,跟我現在環境裡的路徑不一樣,才發現是 3.0 的。回頭翻到文章開頭,才看到 gedit 2 的 plugin howto ,就依法施為,大致上沒什麼問題。這邊分享幾個心得:

  1. 除錯可以用 print,但執行 gedit 時,要在 terminal 下,這樣才會看的到這些印出的訊息。
  2. 基本上 plugin howto 裡寫的相當清楚,但你需要搭配 pygtk2 references 來看,例如 howto 裡提到 gedit.Window.get_active_document 會傳回 gedit.Document,再去看 gedit.Document 一節裏面,裏面說 gedit.Document 就是根植於 gtksourcebuffer,再去找到 gtksourcebuffer (在 gtksourceview 網站),裏面又提到是繼承自 gtktextbuffer,再去翻 gtktextbuffer ,就知道有哪些函式可用。
  3. 對 gtk 的處理要有一定的了解。

 

OpenOffice/LibreOffice Calc Macros(4)

填日期的方法,參考這篇:Calc Examples跟這篇Les champs Date / Calendriers

簡單的說,日期要先丟 “d/m/y” 的值進去,或者是用設定公式的方式去設定日期,然後再去設定 format。

[python]
oDoc = XSCRIPTCONTEXT.getDocument()
oSheet = oDoc.Sheets.getByIndex(0)

oSheet.getCellByPosition( 0, 0 ).setFormula( “=DATE(2004;09;30)” )
oSheet.getCellByPosition( 0, 1 ).setFormula( “10/31/2004” )
oSheet.getCellRangeByName( “A3” ).setFormula( “12/31/2004” )

#—–
# Format the date cells as dates.
com_sun_star_util_NumberFormat_DATE = uno.getConstantByName( “com.sun.star.util.NumberFormat.DATE” )
oFormats = oDoc.getNumberFormats()
oLocale = uno.createUnoStruct( “com.sun.star.lang.Locale” )
nDateKey = oFormats.getStandardFormat( com_sun_star_util_NumberFormat_DATE, oLocale )
oCell = oSheet.getCellRangeByName( “A1:A3” )
oCell.NumberFormat = nDateKey
[/python]

至於要改格式為 YYYY/MM/DD 的方法,我還沒研究出來。

csv與StringIO

看了 python 網站上對 csv 的說明,就在想是不是一定只能藉著開檔才能使用呢?後來查了一下,然後看到 StringIO,藉著這個,就可以把字串以類似檔案的方式來操作了。

[python]
import csv
from StringIO import StringIO

def parse_to_get_record( csv_content ):
“””
According to csv to parse result.
“””
csv_lines = csv_content.splitlines()
# 還可以濾掉某些不要的行
csv_reader = csv.reader( StringIO( ‘\n’.join(csv_lines[2:-2]) ) )
result = []
for row in csv_reader:
print( row )
result.append( row )
return result

f = open(‘d:\\tmp\\aaa.csv’, ‘r’)
s = f.read()
print( parse_to_get_record(s) )
[/python]

pip freeze與還原

用virtualenv,除了可以建出一個開發環境之外,也不會因為distribution不支援而扼腕,然後也可以輕易地安裝、搜索跟反安裝。另外一個好處就是可以輕易的把整份環境給凍結起來。用 pip freeze > requirement_file 可以把開發環境中有安裝的package都列出來,然後再用 pip install -r requirement_file 就可以裝回去。

dateutil.parser解析日期時間字串出現”iter() returned non-iterator of type ‘_timelex'”

之前用python-dateutil的parse在解析字串是沒問題的,結果今天用的時候,卻出現 “iter() returned non-iterator of type ‘_timelex'” 的錯誤,仔細看過,發現之前用的是1.5,而目前用的卻是2.0。上官方網站去看,發現1.5是for Python2,而2.0是for Python3,為什麼不能相容呢?一時之間也無法解決,乾脆就降級用回1.5了,還好用virtualenv跟pip,還蠻簡單的,就先 pip uninstall python-dateutil 再 pip install python-dateutil==1.5 就行了。

UnicodeDecodeError when logging utf-8 string

我的python有使用logging library,可是卻出現下面的錯誤訊息:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 56: ordinal not in range(128)

百思不得其解,明明我的字串就是utf-8,可是卻會出現這個錯誤訊息。查了Python的Unicode How-To好幾次,覺得問題應該是出在檔案上,開檔案時應該要用codecs,那,會不會是logging開啟檔案時,沒有用codecs去開檔案然後處理encoding啊??發現好像也不是,因為使用FileHandler時有指定編碼啊。
上網找了之後,才發現logging的確已經使用codecs來開啟檔案了,那為什麼呢??又再找了幾篇當參考:UTF-8 In Python logging, how?UnicodeEncodeErrors with celery built-in console logging,也有人直接自訂formatter來解決,看著看著,就想到,原來logging裡面已經有處理了啊,再次對utf-8字串作utf-8 encode的結果就是出錯,那就表示不必特別丟utf-8字串,只要丟給他unicode字串,logging就會自動幫我轉了啊~
於是我就不特別再作字串的轉換,直接使用unicode字串,這樣就解決這問題了。

SSL3_GET_SERVER_CERTIFICATE

這是根據錯誤訊息找到的文:Curl: SSL certificate problem, verify that the CA cert is OK – ademar@toronto,但很可惜,對我沒用。

我是用virtualenv去建出我所需的python環境的,我安裝了oauth2,oauth2連帶安裝了httplib2,試著寫一個小程式想試試看oauth2時,卻吐出了這樣的錯誤:[Errno 1] _ssl.c:480: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed。接下來的情況,就幾乎是鬼打牆,找了一堆,都是講要更新憑證。後來靈機一動,因為在某篇文看到說可以用curl_setopt跳過檢查認証,所以就跑去看httplib2的源碼,好死不死在 site-packages/httplib2 下被我看到 cacerts.txt,啊哈,應該就是你吧,就去這裡cURL – Extract CA Certs from Mozilla下載了cacert.pem,然後拿這個檔案替換了cacerts.txt,就搞定了認証的問題。

BaseHTTPServer

模組的文件簡單到不行,而網路上查到的文件大多都是跟你講怎麼弄一個簡單的HTTP Server,真的要寫一個簡單的應用時,卻沒告訴你該怎麼去parse參數。這篇有答案:PyMOTW: BaseHTTPServer

基本上,do_GET時,要用 parsed_path = urlparse.urlparse(self.path) 。而 do_POST 時,要[python]form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={‘REQUEST_METHOD’:’POST’,
‘CONTENT_TYPE’:self.headers[‘Content-Type’],
})
[/python]拿到的 form,可以用 form[“your_key”] 去找到指定參數的值,但拿到的值,型態是MiniFieldStorage,要用 value 屬性去拿真正的值,也就是 form[“your_key”].value 才是真正的值,該文裡也有上傳檔案處理的範例。

twisted筆記

原本想用deferred搭subprocess去做的,想不到twisted已經有包這部份了,就呼叫reactor.spawnProcess就好,文件可以看Twisted Documentation: Using Processes。主要要實作ProcessProtocol,這可以用來知道process狀態,或是拿process輸出做處理…等等的。

作HTTP Server時,會要實作twisted.web.resource.Resource,render_GET裡的request可以參考twisted.web.http.Request : API documentation,引用參數,可以用args屬性,這是一個dictionary。除了render_GET,當然也可以用render_POST、request_HEAD…