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