Могу ли я использовать представление базы данных в качестве модели в Django?
Я хотел бы использовать представление, которое я создал в моей базе данных, в качестве источника для моего django-представления.
Это возможно, без использования пользовательских SQL?
****** 13/02/09 ОБНОВЛЕНИЕ ***********
Как и во многих ответах, вы можете просто создать собственное представление в базе данных, а затем использовать его в API, определив его в models.py.
какое-то предупреждение, хотя:
- manage.py syncdb больше не будет работать
- представлению в начале своего имени требуется то же самое, что и всем остальным моделям (таблицам), например, если ваше приложение называется "вещь", то ваше представление должно называться thing_$viewname
5 ответов
Начиная с Django 1.1, вы можете использовать Options.managed для этого.
Для более старых версий вы можете легко определить класс Model для представления и использовать его, как и другие представления. Я только что протестировал его с помощью приложения на основе Sqlite, и, кажется, он работает нормально. Просто добавьте поле первичного ключа, если столбец "первичного ключа" вашего представления не называется "id", и укажите имя представления в параметрах Meta, если ваше представление не называется "app_classname".
Единственная проблема заключается в том, что команда syncdb вызовет исключение, так как Django попытается создать таблицу. Вы можете предотвратить это, определив "view models" в отдельном файле Python, отличном от models.py. Таким образом, Django не увидит их, когда будет анализировать models.py для определения моделей, создаваемых для приложения, и поэтому не будет пытаться создать таблицу.
Просто обновление для тех, кто столкнется с этим вопросом (от Google или чего-то еще)...
В настоящее время Django имеет простой "правильный способ" определения модели без управления таблицами базы данных:
Options.managed
По умолчанию
True
Это означает, что Django создаст соответствующие таблицы базы данных вsyncdb
и удалить их как частьreset
команда управления. То есть Django управляет жизненными циклами таблиц базы данных.Если
False
для этой модели операции создания или удаления таблицы базы данных не будут выполняться. Это полезно, если модель представляет существующую таблицу или представление базы данных, созданное другими способами. Это единственная разница, когдаmanaged
являетсяFalse
, Все остальные аспекты работы с моделью в точности совпадают с обычными.
Я только что реализовал модель, используя представление с 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.
Из официальной документации 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()
Надеюсь, поможет;-)
Мы сделали это достаточно широко в наших приложениях с MySQL, чтобы обойти ограничение Django для единой базы данных. В нашем приложении есть несколько баз данных, которые находятся в одном экземпляре MySQL. Таким образом, мы можем добиться объединения моделей между базами данных, если мы создали представления для каждой таблицы в "текущей" базе данных.
Что касается вставок / обновлений в представления, в наших сценариях использования представление в основном представляет собой "select * from [db.table];". Другими словами, мы не делаем никаких сложных объединений или фильтрации, поэтому триггер вставки / обновления из save () работает нормально. Если ваш сценарий использования требует таких сложных объединений или обширной фильтрации, я подозреваю, что у вас не возникнет проблем для сценариев только для чтения, но могут возникнуть проблемы с вставкой / обновлением. Я думаю, что в MySQL есть некоторые базовые ограничения, которые не позволяют вам обновлять представления, которые пересекают таблицы, имеют сложные фильтры и т. Д.
В любом случае, ваш пробег может отличаться, если вы используете СУБД, отличную от MySQL, но Django на самом деле не волнует, находится ли он над физической таблицей или представлением. Это будет СУБД, которая определяет, действительно ли она функционирует так, как вы ожидаете. Как заметил предыдущий комментатор, вы, скорее всего, будете выбрасывать syncdb из окна, хотя мы успешно обошли его с помощью сигнала post-syncdb, который удаляет физическую таблицу, созданную Django, и запускает нашу команду "create view...". Однако сигнал post-syncdb немного эзотеричен в том, как он запускается, так что будьте осторожны и здесь.
РЕДАКТИРОВАТЬ: Конечно, под "post-syncdb signal" я имею в виду "post-syncdb listener"