postgresql模式在django业务中的应用

实际业务中存在第三方业务或者与第三方系统对接时,如果涉及到数据库的对接,数据库共用同一个,且使用同一个用户,如何在逻辑上将第三方数据和自己的数据进行区分呢。

postgresql模式

模式是postgresql提供的特殊数据库结构,可以在同一个数据库中对数据进行逻辑上区分,实现更方便的管理。

postgresql所有没有明确指定模式的数据,默认的模式是public,也就是说select *from a 也可以写为select *from public.a

模式可以包含表,视图,索引,存储过程等。

模式的优势:

  • 允许多个用户使用一个数据库并且不会互相干扰。
  • 将数据库对象组织成逻辑组以便更容易管理。
  • 第三方应用的对象可以放在独立的模式中,这样它们就不会与其他对象的名称发生冲突。

怎么用

查看所有模式

\dn

Shell2行,8字

创建模式

create schema test_schema;

Shell2行,31字

创建表

create table test_schema.dog(

id int not null,

name varchar(20) not null,

primary key(id)

);

Shell6行,126字

查询

select *from dog;

ERROR: relation "dog" does not exist

LINE 1: select *from dog;

select *from test_schema.dog;

id | name

----+------

(0 rows)

Shell12行,189字

删除模式

删除空模式,直接drop schema test_schema即可,非空模式删除的话需要同时删除包含的所有对象。

drop schema test_schema;

ERROR: cannot drop schema test_schema because other objects depend on it

DETAIL: table test_schema.dog depends on schema test_schema

HINT: Use DROP ... CASCADE to drop the dependent objects too.

drop schema test_schema CASCADE;

Shell8行,278字

django中使用模式

不使用pgboucer

当不使用pgboucer做数据库连接池时,直接在djangosettings.py中配置数据库链接参数即可。

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'OPTIONS': {

'options': '-c search_path=test_schema,public'

},

'NAME': 'db_name',

'USER': 'username',

'PASSWORD': 'password',

}

}

Python13行,350字

注意,两个地方。

  • search_path中模式的顺序就是查找表的顺序,如果一个表在第一个和后续模式中都存在,那么会选中第一个,查询结果为第一个中的表的结果。
  • django中当执行sync_db时,如果设置了search_path,那么表默认会创建到第一个模式下面而不再是默认的public

使用pgboucer

由于pgbouncer不支持参数search_path,所以无法使用多模式。但是如果pgbouncer只访问默认模式的表,则可以定义多个数据库链接,使pgbouncer访问默认模式表,其他访问另一个链接的表,然后覆盖model的objects方法来实现多模式的支持。这个只支持业务上pgbouncer处理的数据库是默认模式,且默认业务不访问其他模式的情况。

#settings.py

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'NAME': 'db_name',

'USER': 'username',

'PASSWORD': 'password',

},

'test_db': {

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'OPTIONS': {

'options': '-c search_path=test_schema'

},

'NAME': 'db_name',

'USER': 'username',

'PASSWORD': 'password',

},

}

# models.py

class TestDbMgr(models.Manager):

def get_query_set(self):

return super(TestDbMgr, self).get_query_set().using("test_db")

Python29行,754字

或者可以使用django db router来选择正确的schema.

#settings.py

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'NAME': 'db_name',

'USER': 'username',

'PASSWORD': 'password',

},

'test_db': {

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'OPTIONS': {

'options': '-c search_path=test_schema'

},

'NAME': 'db_name',

'USER': 'username',

'PASSWORD': 'password',

},

}

DATABASE_ROUTERS = ['路径.TestRouter']

Python23行,627字

实现TestRouter,django在读写时可使用指定的数据库链接

class TestRouter(object):

def db_for_read(self, model, **hints):

if hasattr(model, '_db_router'):

return model._db_router

return 'default'

def db_for_write(self, model, **hints):

if hasattr(model, '_db_router'):

return model._db_router

return 'default'

Python11行,355字

例子model

class Dog(models.Model):

_db_router = 'test_db'

name = models.CharField(max_length=25)

THE END