編寫獨立的Python程式存取Django資料庫

當我們使用Django建立了一個網站的框架後,一般而言,要存取此網站的資料庫基本上是要在Django框架的啟用狀態時進行存取,也就是你的網站需要是在執行中的狀態,我們以瀏覽器向伺服器存取在網站資料夾下的Python程式時,該程式才能夠以Django的ORM方式正確地存取它的附屬資料表。但有時候我們在進行網站資料維護時,尤其是一些比較耗時的資料處理程式時,其實是需要編寫另外獨立的程式讓管理者在伺服器上(或開發環境中)執行的,本文簡單地記錄了獨立程式存取Django資料庫的方法。

在開始之前要留意的是,Django框架在程式內是以ORM的方式而不是SQL程式存取資料表,它的資料表是在models.py中以class類別的方式所定義的,實際資料表的格式以及資料型態,是透過python manage.py makemigrations以及python manage.py migrate指令進行遷移轉換的,所以,如果你想要以獨立的程式利用SQL指令去直接存取Django網站的資料,是非常高風險的行為。因此,正確的方法是,在你的程式中導入Django資料庫的設定環境,仍然以ORM的方式存取它的資料表。

所以,重點是,只要在你的獨立Python程式(直接在Shell命令提示字元環境中執行,而非透過網頁伺服器委派)中準備好和你的Django網站一樣的環境,就可以順利地操作資料庫了。那麼,如何準備這樣的環境呢?

如果你只是要執行簡單的操作,沒有幾行指令的話,在命令列中輸入以下的指令,是最便利的方法:

python manage.py shell

沒錯,就是在Django網站的目錄下執行上面這個簡單的指令,它就會幫我們匯入Django網站的環境,讓我們直接使用,畫面如下:

假設models.py是放在mysite的資料夾之下,而且裡面有一個叫做Author的資料表

在上述的交談式介面中,可以使用所有在Django程式中的ORM指令,當然還包括了新增、編輯、及刪除功能。

那麼,如果需要編寫更複雜的程式呢?沒問題,只要在程式的前面加上原本你的網站中在wsgi.py中的設定引入指令,再加上django.setup()就可以了,範例程式如下:

import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tangwww.settings')
django.setup()

from mysite.models import Author

authors = Author.objects.all()
print(authors[:10])

在上面例子的第3行中,假設我們的settings.py是放在tangwww資料夾之下的話,那麼就可以利用透過這行引入所有網站中的設定資料,再利用第4行的django.setup()完成設定作業。接下來,就如你所看到的,在程式中也就可以輕易地利用ORM的方式,存取Author這張資料表了。執行的過程如下(假設上述的程式儲存為fixauthor.py):

以下就以一個例子來說明如何把從政府公開資訊網站中取得的資料,利用一個程式儲存到資料庫中。

假設我們想要建立一個流浪動物認養的查詢網站,首先到政府的公開資訊網站中找到以下這個連結:

https://data.gov.tw/dataset/53915

在此連結中可以下載到「臺南待認領養流浪動物資料」,它是以JSON的格式提供下載,點擊該資料之後可以看到以下的內容(只摘錄第1項資料):

[
  {
    "animal_id": 247178,
    "animal_subid": "S110319-02",
    "animal_area_pkid": 16,
    "animal_shelter_pkid": 74,
    "animal_place": "臺南市動物之家善化站",
    "animal_kind": "狗",
    "animal_sex": "F",
    "animal_bodytype": "MEDIUM",
    "animal_colour": "黑色",
    "animal_age": "",
    "animal_sterilization": "F",
    "animal_bacterin": "F",
    "animal_foundplace": "善化區菜市場",
    "animal_title": "",
    "animal_status": "OPEN",
    "animal_remark": "本站動物皆採現場互動面談後評估能否認養 不接受系統上的預約",
    "animal_caption": "",
    "animal_opendate": "2022-03-26",
    "animal_closeddate": "2999-12-31",
    "animal_update": "2022/03/19",
    "animal_createtime": "2022/03/19",
    "shelter_name": "臺南市動物之家善化站",
    "album_file": "",
    "album_update": "",
    "cDate": "2022/03/19",
    "shelter_address": "臺南市善化區昌隆里東勢寮1~19號",
    "shelter_tel": "06-5832399",
    "animal_Variety": "混種狗"
  },
...(省略)
]

從第一個符號我們可以看出它是一個串列的格式,裡面每一個都是字典型態,我們可以從字典的KEY中找出幾個我們感興趣的欄位建立網站的資料表,其中包括animal_id、animal_place、animal_kind、animal_sex、animal_status、animal_remark、animal_update、album_file等等,首先要把這些欄位新建到資料表中,也就是models.py,如下所示:

class Animal(models.Model):
    aid = models.PositiveIntegerField()
    place = models.CharField(max_length=100)
    kind = models.CharField(max_length=20)
    sex = models.BooleanField(default=False)
    status = models.CharField(max_length=20, default="N/A")
    remark = models.CharField(max_length=200)
    update = models.DateField()
    album = models.CharField(max_length=400)
    def __str__(self):
        return "{}({})".format(self.place, self.kind)

然後在admin.py中加入可以管理介面,如下所示:

@admin.register(Animal)
class AnimalAdmin(admin.ModelAdmin):
    list_display = ('aid', 'place', 'kind', 'sex', 'status', 'remark', 'update')    

之後再編寫一個dataimport.py的程式執行之後就可以把所有的資料都順利匯入到Django網站的資料庫中了。由於此程式需要到政府公開資訊網站中下載資料,所以執行之後請在你的虛擬環境中安裝requests模組:

import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nkustweb.settings')
django.setup()
from mysite.models import Animal
import requests, json
url = "https://data.coa.gov.tw/Service/OpenData/TransService.aspx?UnitId=QcbUEzN6E6DL&animal_area_pkid=16"
jsondata = requests.get(url).text
data = json.loads(jsondata)
for item in data:
    try:
        rec = Animal()
        rec.aid = item['animal_id']
        rec.place = item['animal_place']
        rec.kind = item['animal_kind']
        if item['animal_sex']=="M":
            rec.sex = True
        rec.status = item['animal_status']
        rec.remark = item['animal_remark']    
        rec.update = item['animal_update'].replace("/", "-")
        rec.album = item['album_file']
        rec.save()
    except Exception as e:
        print(e)
        pass
print("Done")

在Django網站的主目錄下執行這個程式,之後再進入網站後台就可以看到我們的匯入成果:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *