如何在 Django 中使用模式?
Posted
技术标签:
【中文标题】如何在 Django 中使用模式?【英文标题】:How to use schemas in Django? 【发布时间】:2010-11-12 17:37:38 【问题描述】:我想在 django 中使用 postgreSQL 模式,我该怎么做?
【问题讨论】:
我刚从 Django 开始,让我感到震惊的是,这样的基本功能还没有被原生支持。尤其是当有a 7 year old feature request 开放时。 您能否取消将answer by kmpm 标记为已接受?它不再起作用。 我不再经常使用 Django,所以如果这个问题有一个好的答案,请现在告诉我,这样我就可以将答案标记为最佳答案。 我自己停止使用 Django。恕我直言,您不应该接受任何答案,因为没有一个可以解决此问题。您可以做的最好的事情是更改 SEARCH_PATH,但它仅在您使用单个架构时才有效。 【参考方案1】:也许这会有所帮助。
DATABASES =
'default':
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS':
'options': '-c search_path=your_schema'
,
'NAME': 'your_name',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '5432',
我从以下链接得到答案: http://blog.amvtek.com/posts/2014/Jun/13/accessing-multiple-postgres-schemas-from-django/
【讨论】:
【参考方案2】:我一直在使用:
db_table = '"schema"."tablename"'
过去没有意识到只对只读操作起作用。当您尝试添加新记录时,它会失败,因为序列类似于“schema.tablename”_column_id_seq。
db_table = 'schema\".\"tablename'
到目前为止确实有效。谢谢。
【讨论】:
我不使用 PostgreSQL,但这也是我让它在 SQL Server 中工作的方式。 在创建表之前在syncdb中自动创建模式的任何技巧?运行测试套件所必需的。 警告,使用命名有效,但如果使用syncdb或migrate,将无法创建索引 你在哪里具体介绍了该指令? 还需要记住,表名和模式名在 postgres 中是区分大小写的,请全部大写。【参考方案3】:这比棘手的转义要复杂一些。查看 Django 中的 Ticket #6148 可能是一个解决方案或至少一个补丁。它在 django.db 核心中做了一些小的改动,但它有望被正式包含在 django 中。 之后就是说说而已
db_schema = 'whatever_schema'
在 Meta 类中或用于全局变更集
DATABASE_SCHEMA = 'default_schema_name'
在 settings.py 中
更新:2015-01-08
django 中对应的 issue 已经开放了 7 年,那里的补丁将不再起作用。 这个问题的正确答案应该是……
目前你不能在 django 中使用 postgreSQL 模式。
【讨论】:
那是因为补丁/修复还没有实现。 这在 Django 1.6.1 中仍然不起作用。为什么这个答案被标记为接受?甚至怀疑它归类为... 票证#6148 有一个从未包含在内的补丁,而且可能永远不会包含在内。截至撰写本文时,它已经开放了 7 年。 我可能接受了这个答案,因为早在 2009 年它就起作用了。我应该删除接受的标记吗? 正确答案在那里,至少在我更新之后。您不在 django 中使用模式。【参考方案4】:如以下票证中所述:
https://code.djangoproject.com/ticket/6148,我们可以为 django 用户设置search_path
。
实现此目的的一种方法是通过psql
客户端设置search_path
,例如
ALTER USER my_user SET SEARCH_PATH TO path;
另一种方法是修改django应用,这样如果我们重建数据库,django就不会吐出public
schema中的所有表。
为此,您可以覆盖django.db.backends.postgresql_psycopg2.base
中定义的DatabaseWrapper
创建以下目录:
app/pg/
├── __init__.py
└── base.py
这是base.py
的内容
from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper
class DatabaseWrapper(DatabaseWrapper):
def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
def _cursor(self):
cursor = super(DatabaseWrapper, self)._cursor()
cursor.execute('SET search_path = path')
return cursor
在settings.py
中,添加如下数据库配置:
DATABASES =
'default':
'ENGINE': 'app.pg',
'NAME': 'db',
'USER': 'user',
'PASSWORD': '',
'HOST': '',
'PORT': '',
【讨论】:
这看起来像是这个线程中唯一有效的解决方案,但很费力。但它如何与多个“应用程序”一起工作? @Luís de Sousa 我没有看到几个“应用程序”有任何问题。 1年多来,我们一直在使用这种方法来解决生产中缺乏架构支持的问题。 Minguy,我自己没有看到问题,我只是在问怎么做。我目前正在阅读 Django 书的第 5 章。 有a question on this later issue,目前因未知原因关闭。在 Oracle 或 Postgres 上开发的系统中,在 Django 中会对应不同应用程序的多个模式是很常见的。【参考方案5】:我刚刚为这个问题开发了一个包:https://github.com/ryannjohnson/django-schemas。
一些配置后,你可以简单地在你的模型上调用set_db()
:
model_cls = UserModel.set_db(db='db_alias', schema='schema_name')
user_on_schema = model_cls.objects.get(pk=1)
该包使用https://***.com/a/1628855/5307109 和https://***.com/a/18391525/5307109 中描述的技术,然后包装它们以用于 Django 模型。
【讨论】:
【参考方案6】:没有明确的 Django 支持 postgreSQL 模式。
在使用 Django (0.95) 时,我们必须为 PostgreSQL 的 Django 数据库连接器添加一个 search_path,因为 Django 不支持指定由 ORM 管理的表使用的架构。
取自:
http://nxsy.org/using-postgresql-schemas-with-sqlalchemy-and-elixir
一般的反应是使用 SQLAlchemy 来正确构造 SQL。
哦,这是另一个链接,其中包含一些关于您可以使用 Django 基础做什么的建议,并对其进行扩展以尝试支持您的方案:
http://news.ycombinator.com/item?id=662901
【讨论】:
【参考方案7】:我只是说成功了
db_table = 'schema\".\"tablename'
在 Meta 类中,但这真的很难看。而且我只在有限的场景中使用过它——如果你尝试一些复杂的东西,它很可能会崩溃。而且如前所述,它并没有真正得到支持......
【讨论】:
确实很丑,这样你就得自己管理表名了。【参考方案8】:我知道这是一个相当老的问题,但另一种解决方案是更改 SEARCH_PATH。
示例
假设您有三个表。
schema1.table_name_a
schema2.table_name_b
table_name_c
你可以运行命令:
SET SEARCH_PATH to public,schema1,schema2;
并且仅在 django 中通过表名来引用表。
见5.7.3. The Schema Search Path
【讨论】:
这仅在您手动管理数据库时有效。如果您在此设置中使用syncdb
,您最终将在public
架构中使用所有表。【参考方案9】:
对于 SQL 服务器数据库:
db_table = "[your_schema].[your_table]"
【讨论】:
【参考方案10】:https://docs.djangoproject.com/en/dev/topics/db/multi-db/#using-routers
urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from my_app.my_views import ClientViewSet
router = DefaultRouter(trailing_slash=False)
router.register(r'', ClientViewSet, base_name='clients')
urlpatterns = [
path('', include(router.urls)),
]
【讨论】:
以上是关于如何在 Django 中使用模式?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 django 在 mysql 中的两个不同模式中使用两个具有相同名称的表
如何在 Django 中使用来自 urls.py 的变量重定向 url 模式?
Django 迁移:如何只允许在 --fake 模式下运行?