我可以在Django中使用数据库视图作为模型吗?

时间:2009-02-03 16:17:17

标签: django django-migrations django-syncdb

我想使用我在我的数据库中创建的视图作为我的django-view的源。

这可能,不使用自定义sql吗?

****** 13/02/09更新***********

与许多答案一样,您可以在数据库中创建自己的视图,然后在models.py中定义它,在API中使用它。

但是有些警告:

  • manage.py syncdb将不再有效
  • 视图在其名称的开头需要与所有其他模型(表格)相同的内容,例如,如果您的应用程序被称为“事物”,那么您的视图将需要被称为thing_ $ viewname

5 个答案:

答案 0 :(得分:93)

对于那些遇到此问题的人(来自Google或其他任何内容)的更新......

目前,Django对define model without managing database tables有一个简单的“正确方法”:

  

<强> Options.managed

     

默认为True,这意味着Django将在syncdb中创建相应的数据库表,并将其作为reset管理命令的一部分删除。也就是说,Django 管理数据库表的生命周期。

     

如果False,则不会对此模型执行数据库表创建或删除操作。如果模型表示通过其他方式创建的现有表或数据库视图,则此选项非常有用。 managedFalse时,这是唯一的差异。模型处理的所有其他方面与正常情况完全相同。

答案 1 :(得分:32)

自Django 1.1以来,您可以使用Options.managed

对于旧版本,您可以轻松地为视图定义Model类,并像使用其他视图一样使用它。我刚刚使用基于Sqlite的应用程序测试它,它似乎工作正常。如果您的视图的“主键”列未命名为“id”,请确保添加主键字段,如果您的视图未被称为“app_classname”,请在Meta选项中指定视图名称。

唯一的问题是“syncdb”命令会引发异常,因为Django会尝试创建表。您可以通过在不同于models.py的单独Python文件中定义“视图模型”来防止这种情况。这样,Django在内省models.py时不会看到它们,以确定为应用程序创建的模型,因此不会尝试创建表格。

答案 2 :(得分:11)

我刚刚使用postgres 9.4和django 1.8的视图实现了一个模型。

我创建了这样的自定义迁移类:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_previousdependency'),
    ]

    sql = """
    create VIEW myapp_myview as
     select your view here
    """

    operations = [
        migrations.RunSQL("drop view if exists myapp_myview;"),
        migrations.RunSQL(sql)
    ]

我像往常一样写了模型。它适用于我的目的。

注意 - 当我运行makemigrations时,为模型创建了一个新的迁移文件,我手动删除了该文件。

完全公开 - 我的视图是只读的,因为我使用的是从jsonb数据类型派生的视图,并且没有编写ON UPDATE INSTEAD规则。

答案 3 :(得分:3)

我们在使用MySQL的应用程序中广泛地完成了这项工作,以解决Django的单一数据库限制。我们的应用程序有几个数据库存在于一个MySQL实例中。只要我们为“当前”数据库中的每个表创建了视图,我们就可以通过这种方式实现跨数据库模型连接。

对于视图中的插入/更新,根据我们的用例,视图基本上是“select * from [db.table];”。换句话说,我们不做任何复杂的连接或过滤,所以插入/更新触发器从save()工作就好了。如果您的用例需要这种复杂的连接或大量过滤,我怀疑您对只读方案不会有任何问题,但可能会遇到插入/更新问题。我认为MySQL中存在一些潜在的限制因素阻止您更新到跨表的视图,具有复杂的过滤器等等。

无论如何,如果您使用的是MySQL以外的RDBMS,您的里程可能会有所不同,但Django并不关心它是否位于物理表或视图之上。 RDBMS将决定它是否实际按预期运行。正如之前的一位评论者指出的那样,你可能会把syncdb抛到窗外,虽然我们成功解决了一个post-syncdb信号,它丢弃了Django创建的物理表并运行了我们的“create view ...”命令。然而,后syncdb信号在被触发的方式上有点深奥,因此也需要注意。

编辑:当然“post-syncdb signal”我的意思是“post-syncdb listener”

答案 4 :(得分:3)

Django Official Documentation,您可以像这样调用视图:

#import library
from django.db import connection

#Create the cursor
cursor = connection.cursor()

#Write the SQL code
sql_string = 'SELECT * FROM myview'

#Execute the SQL
cursor.execute(sql_string)
result = cursor.fetchall()

希望它有所帮助; - )