postgresql模式在django业务中的应用
实际业务中存在第三方业务或者与第三方系统对接时,如果涉及到数据库的对接,数据库共用同一个,且使用同一个用户,如何在逻辑上将第三方数据和自己的数据进行区分呢。
postgresql模式
模式是postgresql提供的特殊数据库结构,可以在同一个数据库中对数据进行逻辑上区分,实现更方便的管理。
postgresql所有没有明确指定模式的数据,默认的模式是public,也就是说select *from a
也可以写为select *from public.a
模式可以包含表,视图,索引,存储过程等。
模式的优势:
- 允许多个用户使用一个数据库并且不会互相干扰。
- 将数据库对象组织成逻辑组以便更容易管理。
- 第三方应用的对象可以放在独立的模式中,这样它们就不会与其他对象的名称发生冲突。
怎么用
查看所有模式
\dn
创建模式
create schema test_schema;
创建表
create table test_schema.dog(
id int not null,
name varchar(20) not null,
primary key(id)
);
查询
select *from dog;
ERROR: relation "dog" does not exist
LINE 1: select *from dog;
select *from test_schema.dog;
id | name
----+------
(0 rows)
删除模式
删除空模式,直接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;
django中使用模式
不使用pgboucer
当不使用pgboucer做数据库连接池时,直接在django
的settings.py
中配置数据库链接参数即可。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=test_schema,public'
},
'NAME': 'db_name',
'USER': 'username',
'PASSWORD': 'password',
}
}
注意,两个地方。
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")
或者可以使用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']
实现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'
例子model
class Dog(models.Model):
_db_router = 'test_db'
name = models.CharField(max_length=25)