如何在 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 URL 模式中使用十进制数?

如何在 Django 中使用来自 urls.py 的变量重定向 url 模式?

Django 迁移:如何只允许在 --fake 模式下运行?

实现发布-订阅模式时如何在 Django 和 Twisted 之间进行通信?

如何将数据从 django 传递到引导模式?