用 Django 管理現有數據庫

在多數項目中,總有一些幾乎一成不變的 CRUD 操做,編寫這些代碼很無聊,但又是整個系統必不可少的功能之一。咱們在上一個項目中也面臨相似的問題,雖然已經實現了一個功能相對完整的管理後臺,也儘可能作到了代碼複用,但隨着項目規模的增加,須要編寫的樣本代碼也不斷膨脹,佔用了大量開發時間。python

面對這種局面,我天然想到了 Django。要知道, Django Admin 幾乎就是爲這種需求量身定製的。但對於咱們的項目而言,還有幾個問題要解決:sql

  • 咱們的數據庫使用 SQL Server。Django 默認對此沒有很好的支持;
  • 數據庫結構是由另外一個工具管理的,Django 並無直接修改數據庫結構的權限。因*
  • 此,咱們不能使用 Django migrate;

出於一樣的理由,咱們沒法在數據庫中建立 Django Admin 內置要求的數據表(包括 auth/session 等)。
下面咱們來解決這些問題。若是你碰到相似狀況的話,能夠參考本文的作法。數據庫

SQL Server 支持

遺憾的是,針對 Django 開發的 SQL Server 適配器雖然有幾種,但都比較古老了,對新版的 Django 支持存在問題。通過嘗試,咱們選擇了 Django-Mssql,雖然功能是可用的,但該庫只支持到 Django 1.8,經測試,對 Django 1.11 不兼容,Django 2.x 就更不行了。好在咱們並不須要很新的功能,所以就用 virtualenv 鎖定版本了:django

Django==1.8
django-mssql==1.8
pywin32==223

  在這裏仍是要推薦下我本身建的Python開發學習羣:725479218,羣裏都是學Python開發的,若是你正在學習Python ,小編歡迎你加入,你們都是軟件開發黨,不按期分享乾貨(只有Python軟件開發相關的),包括我本身整理的一份2018最新的Python進階資料和高級開發教程,歡迎進階中和進想深刻Python的小夥伴
django-mssql 是 Windows 版的庫,幕後使用了 ADO 爲驅動,所以同時還要安裝 pywin32。後端

多數據庫

針對第二和第三個問題基本上有兩個思路。第一個是經過實現自定義的 Backend 來跳過 Django 內置的、基於數據庫的實現。從原理上來說是行得通的,但簡單嘗試了一下,發現要自定義的部分至關多,工做量太大。總之,這條路不是很可取。服務器

第二個思路是利用 Django 的多數據庫支持。既然業務數據庫不可由 Django 來管理,那麼就再用一個數據庫來支持 Django 的基本功能,而 Django 對業務數據庫只做查詢和更新,不執行 migrate。固然,爲了使用多個數據庫,咱們須要在配置上多作一些工做。因爲使用後臺的用戶基本上只有公司內部的業務人員,數據量不會大,用服務器級的數據庫有牛刀之嫌。處於簡便考慮,這裏使用默認的 SQLite 做爲內置數據庫:session

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'mydb': {
        'ENGINE': 'sqlserver_ado',
        'HOST': '127.0.0.1',
        'NAME': '<DB_NAME>',
        'USER': '<DB_USER>',
        'PASSWORD': '<DB_PASSWORD>',
        'OPTIONS': {
            'provider': 'SQLOLEDB',
        }
    }
}

須要說明,Django-mssql 爲 provider 選項提供的默認值(按照官方文檔應爲 SQLCLI10)實測會致使出現「找不到提供程序」 的錯誤。因爲 provider 的設置取決於 ADO 的註冊信息,不必定在全部機器上都相同,因此你可能須要本身測試決定哪一個選項可用。app

如今咱們配置了兩個數據源,但還須要告訴 Django 它們和模型的對照關係。實現這一點能夠在語句/實體/全局等多種級別定義。對於咱們的需求而言,對應關係是固定的,逐個模型定義並沒有必要,經過全局定義是最簡單的。實現這必定義的對象在 Django 的術語中稱爲數據庫路由(Database Router)。首先在 settings.py 中定義類名:ide

DATABASE_ROUTERS = ['project.db.MyAppRouter']

而後完成類的實現:工具

class MyAppRouter:
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'myapp':
            return 'myapp'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'myapp':
            return 'myapp'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return False

數據路由須要按照 Django 的要求實現四個方法。其中主要是讀寫兩個方法,咱們須要根據傳來的模型決定匹配到哪一個數據源。 其餘兩個方法目前意義不大,按照默認的實現便可。

定義模型

配置到此完成,接下來須要建立模型。對於已經存在的數據表,能夠用管理命令 inspectdb 反向生成代碼,減小一些手工輸入的負擔。但生成的代碼未必徹底符合你的要求,因此仍是應該本身檢查一下。對於 SQL Server,若是主鍵名不是默認的 id,那麼 inspectdb 彷佛不會自動識別到它們,因此咱們須要檢查一下主鍵字段有無 primary_key,若是沒有的話就加上。

python manage.py inspectdb --database=myapp > myapp\models.py

爲了方便調試和辨別記錄,通常來講咱們還要爲模型類加上 verbose_name 並重載內置的字符串方法。

class XXModel(models.Model):
    XXId = models.BigIntegerField(primary_key=True)
    ...

    class Meta:
        managed = False
        db_table = 'XXModel'
        verbose_name = '模型名稱'
        verbose_name_plural = '模型名稱'

    def __str__(self):
        return self.XXField

把模型添加到 admin,對應的後臺管理信息就完成了。

admin.site.register(XXModel, XXAdmin)

運行程序

最後,爲內置數據庫生成必要的表,建立管理員帳戶,便可運行程序。如下命令就無需說明了:

$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver

總結

咱們第一個版本的後臺程序是本身手工編碼完成的,用了大概兩週的時間。問題在於,每增長一個模型都要手工添加大量樣本代碼。而改寫成 Django 只用了一天時間,包括熟悉相關資料和使用方法,增長一個模型只需花幾分鐘。這也是爲何不少了解 Django 的開發者轉移到其餘平臺之後,會尋找相似的項目。就我瞭解的範圍,Spring Boo 和 Django 在概念上比較相似,但 Boo 主要走的是代碼生成的路線,複雜度更高,理論上靈活性也應該更好一些(我沒有深度研究過)。Nodejs 社區有 Keystone.js 和 Sails.js,不過前者專門針對 MongoDB,後者支持多種數據庫後端,但風聞最近有中止開發的跡象。.Net 社區之前有一個 DynamicData,如今彷佛也沒了下文。發展多年的 Django 也應該算是同類產品中最成熟、生態也最爲完整的產品了。

Django 潛在的問題在於不夠現代化的界面,以及深度定製較爲困難。不過對於咱們的後臺應用來講,這些都是能夠接受的代價。

相關文章
相關標籤/搜索