2011年3月9日 星期三

[Python] Django 之資料庫與 Models 使用筆記

用了 Django 一陣子,常常會碰到 Datetime 的問題,乾脆記一下。


建立資料表時,使用到 DateTimeField:


from django.db import models
import datetime

MyDatetime((models.Model):
# 新增資料必要欄位
myid = models.CharField(max_length=255)

# 新增資料必要欄位, 沒有指定 mydate1 數值或其格式不對時會出錯
mydate1 = models.DateTimeField()

# 新增資料非必要,允許 mydate2 為 None 或不設定
mydate2 = models.DateTimeField(null=True, blank=True, default=None)


在 views 寫資料:


from myproj.myapp.models import MyDatetime

def MyInsert(request):
_myid = request.POST.get('myid',None) or request.GET.get('myid',None)
_mydate1 = request.POST.get('mydate1',None) or request.GET.get('mydate1',None)
#_mydate2 = request.POST.get('mydate2',None) or request.GET.get('mydate2',None)

try: # 格式轉換, 假設 mydate1 輸入格式是 "%Y/%m/%d %H:%M:%S",無法直接使用,需轉成 "%Y-%m-%d %H:%M:%S" 格式
_mydate1 = datetime.datetime.fromtimestamp(time.mktime(time.strptime( _mydate1 , "%Y/%m/%d %H:%M:%S"))).strftime("%Y-%m-%d %H:%M:%S")
except:
_mydate1 = None # mydate1 欄位不能為空,若在此步,繼續進行下去新增資料會出錯

try:
# 先確認此筆資料是否存在,若存在則更新 mydate2
obj = MyDatetime.object.get( myid=_myid )
# 設定 mydate2 為當地時間
obj.mydate2 = strftime( "%Y-%m-%d %H:%M:%S" , localtime() )
obj.save()
except Exception, e:
obj = MyDatetime(
myid = _myid , 
mydate1 = _mydate1 ,

# mydate2 預設可以為 None,所以不輸入也行,但記得 _mydate2 可以為 None 但不能為 '' 字串
#mydate2 = _mydate2 ,
)
obj.save()


查詢資料時,使用 QuerySet 提供多重的條件限制:


from django.db.models import Q

from django.shortcuts import render_to_response
from django.template import RequestContext
from django import http
 
import simplejson

def MyQuery(request):
_myid = request.POST.get('myid',None) or request.GET.get('myid',None)
  _mydate1 = request.POST.get('mydate1',None) or request.GET.get('mydate1',None)
_mydate2 = request.POST.get('mydate2',None) or request.GET.get('mydate2',None)
 
# 使用 and 條件
try:
obj = MyDatetime.object.get( Q(myid=_myid) & Q(mydate1=_mydate1) )
except:
pass
 
  # 使用 or 條件
try:
obj = MyDatetime.object.get( Q(myid=_myid) | Q(mydate1=_mydate1) )
except:
pass

# 多重條件 ( ( myid == _myid || mydate1 == _mydate1 ) && ( mydate2 == _mydate2 ) )
try:
obj = MyDatetime.object.get( Q( Q(myid=_myid) | Q(mydate1=_mydate1) ) & Q(mydate2=_mydate2) )
except:
pass

# 使用大小判斷 great than , less than, equal
try:
obj_list = list( MyDatetime.object.filter( Q(mydate1__gt=_mydate1) ) )
except:
pass
try:
obj_list = list(  MyDatetime.object.filter( Q(mydate1__lt=_mydate1) ) )
except:
pass
try:
obj_list = list( MyDatetime.object.filter( Q(mydate1__gte=_mydate1) ) )
except:
pass
try:
obj_list = list( MyDatetime.object.filter( Q(mydate1__lte=_mydate1) ) )
except:
pass

_result = {}

# 取出 list 並 sorting
try:
obj_list = list( MyDatetime.object.all() )
obj_list.sort( cmp=lambda x,y: cmp( x.myid , y.myid ) )
output = []
for obj in obj_list:
_obj = {}
_obj['myid'] = obj.myid
output.append( _obj )
_result['result'] = output
exception:
pass

# 回傳 JSON 格式
result=simplejson.dumps(_result)
return http.HttpResponse(str(result))


2011年3月8日 星期二

GIS 與 GPS 座標轉換

快速地再網路上找尋一陣子,沒有看到很明確的轉換公式?不知是不是已有一些常用的 library ?暫時只找到中研院 GIS 小組,該網站上呈列出眾多開發的小工具程式 - GIS應用支援工具集,其中就看到了兩樣有關:


WGS84_TM2



Web版坐標轉換程式 - http://webgis.sinica.edu.tw/cgi-tran/webtrans.htm


但前者都是 Windows 程式,甚至連 Web 版呼叫的 CGI 都是 exe 檔案,一時之間,就先用 Web 版頂著用 XD 過幾天再來找找或寫一下 Python 版本好了


Python:


def WebQueryGPSToGIS(lat,lon):
        x = None 
        y = None 
        err = None 
        if lat <> None and lon <> None:
                try: 
                        raw_data = urllib.urlopen( 'http://webgis.sinica.edu.tw/cgi-tran/wgstrans.exe?module=5&Lat='+str(lat)+'&Lot='+str(lon) ).read()
                        m = re.search( r"([0-9\.]+),([0-9\.]+)" , raw_data )
                        x = m.group(1)
                        y = m.group(2)
                except Exception, e:
                        err = str(e)
        return { 'x': x, 'y': y, 'lat': lat, 'lon' : lon, }
        #return { 'x': x, 'y': y, 'lat': lat, 'lon' : lon, 'e': err }


後來有找到 Taiwan datums - OSGeo Wiki,上頭有提到 Perl - Geography-NationalGrid-TW-0.08,有空再來改寫成 Python 好了。


使用 Galileo 與 Mobile Atlas Creator 之離線地圖測試心得

之前曾寫過幾篇關於離線地圖的相關測試:



可惜了上述的 xGPS 需要 Jailbreak 過後才能使用,這對一般人不太適用。爾後翻了以前的書籤:自製離線地圖,iPhone 變身GPS,才想起有這麼一款不用 JB 可以使用得離線軟體。



Galileo Offline Maps


Galileo Offine Maps 是免費的軟體並且還支援 iPad 大小(但看之前的文章顯示,以前下載還需要付費的),而 xGPS 僅 iPhone 大小。兩者稍微試用,前者用起來的操作介面還滿流暢的,但他只算是部分免費,因為如果要把自製的離線地圖透過 iTunes 傳進此 app 來使用,則需要花費 1.99 美金才能啟用這個功能。至於不花錢的用法?那就是用此套軟體去趁著有網路的時候快點瀏覽地圖來 cache 囉,但他只提供如 OpenStreetMaps 這類而已,這很合情合理,因為 Google Maps 的使用版權本來就是要線上使用。不過透過上述文章,裡頭有教怎樣自製離線地圖,以便匯入 Galileo 裡頭,筆記一下在 Windows XP 的操作流程:



  1. 下載 Java 環境

  2. 下載 Mobile Atlas Creator 1.8.zip 並解壓縮

  3. 下載 sqlitejdbc-v056.jar 擺在上述目錄中

  4. 執行 Mobile Atlas Creator.exe

  5. 挑選 Map source

  6. 左鍵滑鼠按住可移動地圖,右鍵滑鼠按住可框住想要下載的地圖

  7. 勾選 Zoom Levels 

  8. 填寫 Atlas Content 裡的 name 並按下 Add selection

  9. 選擇輸出格式,依文章說要在 Atlas settings 選 RMaps SQLite

  10. 按下 Create Atlas 就會開始下載,成果就擺在 Mobile Atlas Creator 1.8 目錄中,如 xxx.sqlitedb,而 Galileo 也是認 *.sqlitedb 檔名為匯入的地圖,像 xGPS 的產出是 *.db ,雖然只要改一下副檔名也就會辦認出來,只是兩者儲存格式並非一樣

  11. 剩下的操作透過 iTunes 傳檔進 Galileo 以及在 Galileo app 裡購買啟用功能,此部分我就沒試了


其他細節請多查看 自製離線地圖,iPhone 變身GPS 此篇文章,已經講得滿詳細了,有的地方還有提到要調大 JAVA 運行的記憶體等。該篇文章下載地圖的軟體是 Mobile Atlas Creator,試用的結果支援的地圖來源還滿多的,並且輸出的平台也是一卡車多


地圖來源:


Input


輸出平台:


MAC_output


比較讓我好奇的實作的方式,並且查看 xGPS Manager 跟 Mobile Atlas Creator 的產生檔案,兩者都是 SQLite ,也讓我覺得好像可以共用?當我用 Firefox SQLite Manager 開啟查看後,發現邏輯上不會差太多,但儲存的欄位名稱不同,應該是不能共用的吧。


xGPS Manager:


sqlite_xgps


Mobile Atlas Creator:


sqlite_atlas


看來離線地圖是一個很稀鬆平常的需求,從 Mobile Atlas Creator 可以查看到一排平台,也有可能是以前網路不發達的關係:


AFTrack (Symbian)
AlpineQuest (Android)
AndNav (Android)
Big Planet Tracks SQLite format (Android)
CacheBox (Windows Mobile)
Cachewolf
Garmin Custom Map - KMZ (GPS handhelds)
Glopus (Pocket PC)
Google Earth
GPS Sport Tracker
Magellan RMP (GPS handhelds) & VantagePoint
Maplorer (Windows CE/Windows Mobile)
Maverick (Android)
Mobile Trail Explorer (J2ME) - single tiles and MTECache file
NaviComputer (Windows Mobile)
OruxMaps (Android)
OsmAnd
OSMtracker (Windows Mobile/Pocket PC)
OziExplorer (single 24bit PNG image with calibration (MAP) file
PathAway (Windows Mobile)
RMaps SQLite format (Android)
[Nokia] Sports Tracker
Touratech QV (Windows software, commercial)
TrekBuddy (J2ME, Android)
u-blox
and others


以操作性來說,我覺得 xGPS Manager 花的步驟比 Mobile Atlas Creator 少很多,也是因為 xGPS Manager 只能支援 xGPS 罷了,而 app 的使用上,我覺得 Galileo Offine Maps 用起來的感覺比 xGPS 順暢。而 xGPS 大概是因為什麼東西都吃 Google 的,導致他在 App store 無法上架吧?據說 App store 很嚴格的,如果也學 Galileo 的話,應該要上架沒啥問題吧。


今天中午還在跟同事閒聊離線服務的價值,盡管網路這幾年的便利性已經大大的普及了,我還是覺得離線性的應用服務還是不少的,畢竟服務是看需求的啦,但也不能一昧追求離線型或永遠思考有網路用。


2011年3月7日 星期一

[Python] 使用 Django 環境開發 commands/tools

在 Django framework 下開發許多功能,結果突然想要用到 tools 模式時,想到大部分都是在 python manager shell 下進行,一時之間沒想到好解法,例如想要定期跑某個程式時,只想到弄成 CGI 模式,用 wget 搭配 crontab 去啟動事件。


今天跑去問了前輩,前輩就跟我說有可以寫成 tools 的方式:Django | Writing custom django-admin commands | Django documentation,經測試也滿成功的。


筆記一下:


假設專案叫 myproj ,並且裡頭有個 myapp,目錄結構如下:


/path/myproj/myapp/
/path/myproj/settings.py
...


接著在 myapp 內建立 management/commands 結構:


$ mkdir -p /path/myproj/myapp/management/commands
$ touch /path/myproj/myapp/management/__init__.py
$ touch /path/myproj/myapp/management/commands/__init__.py
$ vim /path/myproj/myapp/management/commands/mycmd.py

from django.core.management.base import BaseCommand, CommandError
from myproj.myapp import views as v

class Command(BaseCommand):
args = '<poll_id poll_id ...>'
help = 'Closes the specified poll for voting'

def handle(self, *args, **options):
for poll_id in args:
if pool_id == 'test':
print 'test'


如此一來,就可以使用 tools 模式執行,而本身就只要去改上述 print 'test' 的部分,弄成想要跑的函數:


$ cd /path/myproj && python /path/myproj/manager.py mycmd test
test


還算滿簡單便利的,細節就請到官網查看囉。 


2011年3月5日 星期六

免費的虛擬機器服務 - Cloudshare Pro


Cloudshare 提供虛擬機器服務,申請免費帳號的過程需填寫手機號碼並做簡訊認證,不像其他家需要填寫到信用卡。這幾天試用了一下,免費帳號可以開啟 3 台虛擬機器,但不能調整機器內的硬體狀況,如記憶體、硬碟空間等,共有多種作業系統可挑選,如 Windows XP Pro(記憶體1GB, 硬碟12GB), Windows server 2003(記憶體1GB, 硬碟12GB)、Ubuntu 10.04 server(記憶體512MB, 硬碟16GB)、Ubuntu 10.04 desktop(記憶體1GB, 硬碟24GB) 等。


操作流成僅需在網站上點選幾步,就能自動啟動機器,接著透過瀏覽器與預設帳密進行 console 的瀏覽,也能從 [Edit Environment]->[Edit users & access] 新增或修改 console 登入的帳密,除此之外,也可以登入作業系統變更管理者的密碼,以便進行遠端連線。


整體上算是一個不錯的虛擬機器服務,目前我常用的方式:



  • 在 cloudshare 開一台 Ubuntu 10.04 server

  • 登入 Ubuntu 後稍作處理,記得要做系統更新

    • $ passwd

    • $ sudo apt-get update && sudo apt-get upgrade

    • $ sudo vim /etc/hosts.allow
      ALL: MyIP

    • $ sudo vim /etc/hosts.deny
      sshd: *

    • $ mkdir ~/.ssh



  • 在常用機器處理,如此以來提高便利行

    • $ ssh-keygen -t rsa -P ''

    • $ scp ~/.ssh/id_rsa.pub user@pub#-###.env.cloudshare.com:~/.ssh/authorized_keys

    • $ vim ~/.cshrc
      alias cloudshare        ssh user@pub#-###.env.cloudshare.com 




至於 cloudshare 提供的 External Address: pub#-###.env.cloudshare.com,就是用來遠端登入用的,可以透過 nslookup pub#-###.env.cloudshare.com 得知 public ip 囉!


目前我把它定位在個人的宅宅實驗平台,但對於一些機密類的帳戶或是敏感資料,暫時還會避開使用。現在我可以想到的是架 proxy 來翻牆 XDDD 這陣子太愛玩 proxy 囉!除此之外我還是比較常用 Virtualbox 啦,而 cloudshare 的最大缺點是...若一陣子沒在 cloudshare 網站上活動(console?!)就會被 suspend,這個訊息在網頁上也有訊息提示:


Environment will suspend after 30 minutes of inactivity


CloudShare provide its service for a fantastically low price because we suspend the environment when you are away. CloudShare will start counting away, or inactivity, time when you are not accessing the environment using our web pages. 


Sometimes, you need the environment to stay alive a little bit longer. To that effect, we have added, for ProPlus users, the ability to extend the environment inactivity timeout up to 60 minutes


至於機器從 suspend 起來後,會改變的有 External Address (pub#-###.env.cloudshare.com) 但 Internal IP (10.x.x.x) 則不會變,如果要架 Hadoop 或彼此會相連的應用,就還是盡量用 internal ip 囉。