web-dev-qa-db-fra.com

Puis-je utiliser une vue de base de données comme modèle dans Django?

je voudrais utiliser une vue que j'ai créée dans ma base de données comme source pour ma vue Django.

Est-ce possible, sans utiliser SQL personnalisé?

****** MISE À JOUR 13/02/09 ***********

Comme le suggèrent de nombreuses réponses, vous pouvez simplement créer votre propre vue dans la base de données, puis l'utiliser dans l'API en la définissant dans models.py.

un avertissement cependant:

  • manage.py syncdb ne fonctionnera plus
  • la vue a besoin de la même chose au début de son nom que tous les autres modèles (tableaux) par exemple si votre application est appelée "chose" alors votre vue devra être appelée chose_ $ nom_vue
60
spence91

Depuis Django 1.1, vous pouvez utiliser Options.managed pour cela.

Pour les versions plus anciennes, vous pouvez facilement définir une classe de modèle pour une vue et l'utiliser comme vos autres vues. Je viens de le tester à l'aide d'une application basée sur Sqlite et cela semble bien fonctionner. Assurez-vous simplement d'ajouter un champ de clé primaire si la colonne "clé primaire" de votre vue n'est pas nommée "id" et spécifiez le nom de la vue dans les options Meta si votre vue ne s'appelle pas "nom_classe_app".

Le seul problème est que la commande "syncdb" lèvera une exception puisque Django essaiera de créer la table. Vous pouvez empêcher cela en définissant les 'modèles de vue' dans un Python, différent de models.py. De cette façon, Django ne les verra pas lors de l'introspection models.py pour déterminer les modèles à créer pour l'application et donc ne tentera pas pour créer la table.

32
Ferdinand Beyer

Juste une mise à jour pour ceux qui rencontreront cette question (de Google ou autre) ...

Actuellement Django a un simple "bon moyen" pour définir le modèle sans gérer les tables de base de données :

Options.managed

Par défaut, True, ce qui signifie Django créera les tables de base de données appropriées dans syncdb et les supprimera dans le cadre d'une commande de gestion reset. est, Django gère le cycle de vie des tables de base de données.

Si False, aucune opération de création ou de suppression de table de base de données ne sera effectuée pour ce modèle. Cela est utile si le modèle représente une table existante ou une vue de base de données qui a été créée par d'autres moyens. C'est la différence seulement lorsque managed est False. Tous les autres aspects de la gestion des modèles sont exactement les mêmes que la normale.

93
drdaeman

Je viens d'implémenter un modèle utilisant une vue avec postgres 9.4 et Django 1.8.

J'ai créé des classes de migration personnalisées comme ceci:

# -*- 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)
    ]

J'ai écrit le modèle comme je le ferais normalement. Cela fonctionne à mes fins.

Remarque - Lorsque j'ai exécuté makemigrations, un nouveau fichier de migration a été créé pour le modèle, que j'ai supprimé manuellement.

Divulgation complète - ma vue est en lecture seule car j'utilise une vue dérivée d'un type de données jsonb et je n'ai pas écrit de règle ON UPDATE INSTEAD.

12
eceppda

Nous l'avons fait assez largement dans nos applications avec MySQL pour contourner la limitation de base de données unique de Django. Notre application possède quelques bases de données vivant dans une seule instance MySQL. Nous pouvons réaliser des jointures de modèle de bases de données de cette manière tant que nous avons créé des vues pour chaque table dans la base de données "actuelle".

En ce qui concerne les insertions/mises à jour dans les vues, avec nos cas d'utilisation, une vue est essentiellement un "select * from [db.table];". En d'autres termes, nous ne faisons pas de jointures ou de filtrage complexes, donc le déclencheur d'insertion/mise à jour de save () fonctionne très bien. Si votre cas d'utilisation nécessite de telles jointures complexes ou un filtrage étendu, je pense que vous n'aurez aucun problème pour les scénarios en lecture seule, mais que vous risquez de rencontrer des problèmes d'insertion/mise à jour. Je pense qu'il y a des contraintes sous-jacentes dans MySQL qui vous empêchent de mettre à jour dans des vues qui croisent des tables, ont des filtres complexes, etc.

Quoi qu'il en soit, votre kilométrage peut varier si vous utilisez un SGBDR autre que MySQL, mais Django ne se soucie pas vraiment de savoir s'il se trouve au-dessus d'une table ou d'une vue physique. Ce sera le SGBDR qui détermine si elle fonctionne réellement comme prévu. Comme l'a noté un commentateur précédent, vous lancerez probablement syncdb par la fenêtre, bien que nous ayons réussi à le contourner avec un signal post-syncdb qui supprime la table physique créée par Django et exécute notre commande "create view ...". Cependant, le signal post-syncdb est un peu ésotérique dans la façon dont il est déclenché, donc faites attention à emptor également.

EDIT: Bien sûr, par "signal post-syncdb", je veux dire "écouteur post-syncdb"

3
Joe Holloway

Depuis Django Official Documentation , vous pouvez appeler la vue comme ceci:

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

J'espère que cela aide ;-)

3
jobima