Могу ли я использовать представление базы данных в качестве модели в Django? - PullRequest
60 голосов
/ 03 февраля 2009

Я хотел бы использовать представление, которое я создал в моей базе данных, в качестве источника для моего django-представления.

Возможно ли это без использования пользовательских sql?

****** 13/02/09 ОБНОВЛЕНИЕ ***********

Как и во многих ответах, вы можете просто создать собственное представление в базе данных, а затем использовать его в API, определив его в models.py.

хотя некоторые предупреждения:

  • manage.py syncdb больше не будет работать
  • представлению в начале своего имени требуется то же самое, что и всем остальным моделям (таблицам), например, если ваше приложение называется "вещь", то вашему представлению нужно будет называть thing_ $ viewname

Ответы [ 5 ]

93 голосов
/ 15 августа 2009

Просто обновление для тех, кто столкнется с этим вопросом (от Google или чего-либо еще) ...

В настоящее время Django имеет простой «правильный способ» определения модели без управления таблицами базы данных :

Options.managed

По умолчанию True, то есть Django создаст соответствующие таблицы базы данных в syncdb и удалит их как часть команды управления reset. То есть Django управляет жизненными циклами таблиц базы данных.

Если False, никакие операции по созданию или удалению таблицы базы данных не будут выполняться для этой модели. Это полезно, если модель представляет существующую таблицу или представление базы данных, созданное другими способами. Это только разница, когда managed равен False. Все остальные аспекты работы с моделью точно такие же, как обычно.

32 голосов
/ 03 февраля 2009

Начиная с Django 1.1, для этого вы можете использовать Options.managed .

Для более старых версий вы можете легко определить класс Model для представления и использовать его как другие представления. Я только что протестировал его с помощью приложения на основе Sqlite, и, кажется, он работает нормально. Просто убедитесь, что добавили поле первичного ключа, если столбец «первичного ключа» вашего представления не назван «id», и укажите имя представления в параметрах Meta, если ваше представление не называется «app_classname».

Единственная проблема заключается в том, что команда syncdb вызовет исключение, поскольку Django попытается создать таблицу. Вы можете предотвратить это, определив «view models» в отдельном файле Python, отличном от models.py. Таким образом, Django не увидит их, когда будет анализировать models.py для определения моделей, создаваемых для приложения, и поэтому не будет пытаться создать таблицу.

11 голосов
/ 09 апреля 2015

Я только что реализовал модель, используя представление с 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 голосов
/ 23 сентября 2013

Из Официальная документация Django , вы можете назвать вид следующим образом:

#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()

Надеюсь, это поможет; -)

3 голосов
/ 07 февраля 2009

Мы сделали это довольно широко в наших приложениях с MySQL, чтобы обойти ограничение Django для единой базы данных. Наше приложение имеет несколько баз данных, которые находятся в одном экземпляре MySQL. Таким образом, мы можем добиться объединения моделей между базами данных, если мы создали представления для каждой таблицы в «текущей» базе данных.

Что касается вставок / обновлений в представления, в наших случаях использования представление в основном представляет собой "select * from [db.table];". Другими словами, мы не делаем никаких сложных объединений или фильтрации, поэтому триггер вставки / обновления из save () работает нормально. Если ваш сценарий использования требует таких сложных объединений или обширной фильтрации, я подозреваю, что у вас не возникнет никаких проблем для сценариев только для чтения, но могут возникнуть проблемы с вставкой / обновлением. Я думаю, что в MySQL есть некоторые основные ограничения, которые не позволяют вам обновлять представления, которые пересекают таблицы, имеют сложные фильтры и т. Д.

В любом случае, ваш пробег может отличаться, если вы используете СУБД, отличную от MySQL, но Django на самом деле не волнует, находится ли она над физической таблицей или представлением. Это будет СУБД, которая определяет, действительно ли она функционирует так, как вы ожидаете. Как заметил предыдущий комментатор, вы, скорее всего, будете выбрасывать syncdb из окна, хотя мы успешно обошли его с помощью сигнала post-syncdb, который сбрасывает физическую таблицу, созданную Django, и запускает нашу команду "create view ..." Тем не менее, сигнал post-syncdb немного эзотеричен в том, как он запускается, поэтому будьте осторожны с emptor.

РЕДАКТИРОВАТЬ: Конечно, под "post-syncdb signal" я имею в виду "post-syncdb listener"

...