oracle-django總結


參考:

https://stackoverflow.com/questions/54294114/django-inspectdb-ora-00904-identity-column

 

背景:單位運行一批系統,數據庫是oracle11g,java開發,比較老的框架,代碼看不懂。我想到用django作為補丁語言,開發一些微服務接口。

一、技術調查

1. django繼承數據遺產(legacy database),用 python manage.py inspectdb [tablename] ,反向生成model.py

2.Django==1.11.22 可以用inspectdb,反向生成oracle11g的model.py

     django2.x以上,若想對oracle migrate操作,只能針對oracle12c以上。不能作用於oracle11g

        django1.11.22 migrate oracle11g

           django 2.x migrate oracle12c

    參考:https://stackoverflow.com/questions/48002977/how-to-make-django-2-0-to-use-oracle-11g-syntax-instead-of-12c

3. ubuntu linux上,訪問oracle需要2點

 (1)cx_oracle

      (2) oracle instant client

4.最終的解決方案

 (1)安裝2套virtualenv, 一個是django==1.11.22,專門用於反向oracle11g 的table,生成model.py

    另一套venv是生產環境,django>2.x

(2)單位oracle是11g,用django2.x不能migrate, 因為dj2.0是按oracle12c定制的backends, migrate會產生

  (ORA-02000: missing ALWAYS keyword)錯誤。

  那么這些legacy data,

  DDL:手工操作,create table ,add column 等。

  CRUD data: insert table , delete ,update table 等, queryset是支持的。

(3) 建設multiple database ,django運行的表(user, session等)用sqlite, 數據遺產不做migrate,主要用於業務查詢和crud

  參考:https://docs.djangoproject.com/en/3.0/topics/db/multi-db/


二、環境安裝設置記錄
環境問題復雜,不同軟件是否適配需要按官方說明或自己測試。 我按以下測試通過

os:ubuntu 16.04
django==2.2.4(produce) #用於服務運行
django====1.11.22(tmp) #用於inspectdb oracle 11g

1. 安裝cx_oracle
pip install cx-Oracle==6.0 (最新版本也可以cx_oracle==7.3)
2. 安裝Oracle Instant Client RPM
參考:
 https://help.ubuntu.com/community/Oracle%20Instant%20Client
 https://oracle.github.io/odpi/doc/installation.html#linux

下載:oracle-instantclient19.6-basic-19.6.0.0.0-1.x86_64.rpm
 https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html

   

 3.安裝,設置

 sudo apt-get install alien
 sudo alien -i oracle-instantclient19.6-basic-19.6.0.0.0-1.x86_64.rpm
 

  安裝完成后,在/usr/lib/oracle/19.6/client64/lib/network/admin目錄下,制作tnsnames.ora文件,內容如下:

lxg@lxg-opt:/usr/lib/oracle/19.6/client64/lib/network/admin$ cat tnsnames.ora 
234 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 202.205.180.234)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)

注意內容要可讀

lxg@lxg-opt:/usr/lib/oracle/19.6/client64/lib/network/admin$ sudo chmod -R 777 oracle

設置oracle_home

sudo gedit /etc/profile

export ORACLE_HOME=/usr/lib/oracle/19.6/client64
export LD_LIBRARY_PATH=/usr/lib/oracle/19.6/client64/lib:$LD_LIBRARY_PATH

生效

source /etc/profile

 

三、程序運行測試

 1.普通python連接oracle

 

import cx_Oracle

def test1():
    print('開始。。。。。')
    connection = cx_Oracle.connect("jssq/js@234")
    print (connection.version)
    connection.close()

if __name__ == '__main__':
    test1()

輸出:
開始。。。。。
11.2.0.1.0
 

 

2.django測試

(1)setting.py

 

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },

    'oracle': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'orcl',(數據庫的service_name,默認是orcl) 'USER': 'jssq',
        'PASSWORD': 'js',
        'HOST': 'xxx.xxx.xxx.234',(數據庫服務器ip) 'PORT': '1521',
    }
}

(2)  oracle數據庫 

 CREATE TABLE "JSSQ"."JS_MINZU" 

( "BM" VARCHAR2(10),
"MC" VARCHAR2(60),
CONSTRAINT "PK1" PRIMARY KEY ("BM"))

 這是pl/sql工具查看的結果

 

用django1.11.22,反向生成model.py

(py3.6env) lxg@lxg-opt:~/98receive/pystudy/g_oracle$ python manage.py inspectdb  js_minzu > js_minzu.py

生成的model如下,簡單改一下model名稱變成Product(為了使用原來的跑在sqlite的程序)

要在django中正常使用反向生成的model,要求oracle table有且有唯一column的primary key ,不支持聯合主鍵。

from django.db import models

class Product(models.Model):
    bm = models.CharField(primary_key=True, max_length=10)
    mc = models.CharField(max_length=60, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'js_minzu'
managed= False ,Django 將不會為當前 model 創建或者刪除數據庫表。 
通常在表示某個 通過其他方法創建的現有數據表時這會非常有用。這是當 
managed=False 時 僅有 的不同之 處。

以下,migrate oracle數據庫會失敗,因為django2針對oracle12c 有效。我用的orcle11g。
所以,我用雙數據庫,ddl用sqlite,對業務數據oracle只進行crud,不migrage.
(py3.6env) lxg@lxg-opt:~/98receive/pystudy/g_oracle$ python manage.py migrate --database=oracle
System check identified some issues:
cx_Oracle.DatabaseError: ORA-02000: missing ALWAYS keyword

view.py

class ProductList(ListView):
    paginate_by = 6
    model = MYTABLE

    def get_template_names(self):
        template_name = '{}/{}List.html'.format(APPNAME,MYTABLE.__name__)
        return template_name

    def get_queryset(self):
        # user_id = self.request.user.id
        queryset = MYTABLE.objects.using('oracle').all()

        self.filter = ProductFilter(self.request.GET, queryset=queryset)
        return self.filter.qs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context['filter'] = self.filter
        context['model'] = self.model
        return context
using('oracle') ,表示使用oracle數據庫,否則會用default數據庫。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM