[PYTHON] Créez dynamiquement des tables dans un schéma avec Django, générez dynamiquement des modèles

Aperçu

La fonctionnalité ORM de Django est excellente, mais lorsque vous essayez de créer un modèle pour une table légèrement différente, telle qu'une table créée dynamiquement ou une table dans un schéma postgres spécifique, il n'y a pas beaucoup d'informations.

De plus, si vous essayez de faire quelque chose d'un peu compliqué, comme détourner la table créée et créer une table avec la même définition dans un autre schéma, il faut du temps pour enquêter et le processus de développement s'arrête pendant quelques jours.

Cet article est un récit de la lutte pour atteindre les objectifs suivants face à ces défis.

** <Ce que vous voulez réaliser> **

--Je veux créer un modèle qui a la même définition qu'un modèle existant mais qui ne diffère que dans le schéma, en détournant le modèle existant. --Je souhaite utiliser le modèle créé pour ** dynamiquement ** créer une table dans un schéma différent du modèle créé.

En bref, bien que ce soit une exigence légèrement compliquée, la fonction ORM utilisant la classe Model de Django est excellente, je veux donc maximiser les avantages de la création de table, de l'enregistrement des enregistrements, de la recherche, etc.

La motivation en premier lieu

Pourquoi vous souhaitez utiliser un schéma autre que le schéma standard Postgres

--Une des utilisations de schéma décrites dans le document PostgreSQL 10.5 "Une base de données est utilisée par de nombreux utilisateurs. C'est parce que nous voulons réaliser "afin qu'ils puissent être utilisés sans interférer les uns avec les autres". Cette fois, nous visons à réaliser un service d'analyse qui puisse être utilisé par différents utilisateurs, mais afin d'éliminer les interférences entre les données utilisateur, nous voulons préparer un schéma avec la même structure de table pour chaque utilisateur.

Pourquoi souhaitez-vous utiliser des tables et des modèles existants?

environnement

L'environnement cette fois est le suivant.

manière

En conclusion, cela a été possible en appliquant les références. Les détails sont décrits ci-dessous.

Définition du modèle à détourner

Premièrement, pour l'explication suivante, un exemple de modèle qui est une source de détournement est le suivant.

app/models/model.py


class Compound(models.Model):
    name = models.CharField(max_length=1024)
    smiles = models.CharField(max_length=4000, null=True)
    standard_inchi = models.CharField(max_length=4000, default=None, null=True)
    mol = models.TextField(null=True)
    image = models.BinaryField(null=True)

Puisque le modèle de la source de diversion est sous le contrôle de la migration de Django, vous devriez pouvoir créer une table pour le modèle en effectuant une migration, migrez. La table sera alors créée dans le schéma public à moins que vous ne définissiez des paramètres spéciaux.

Créer une fonction qui crée dynamiquement un modèle

Ensuite, la fonction qui est la clé de cette heure sera expliquée. Normalement, dans Django, il est nécessaire de créer au préalable une classe de modèle dans la source, mais cette fois, reportez-vous à Modèles dynamiques et créez le modèle souhaité. J'ai préparé une fonction pour créer dynamiquement une classe. Plus précisément, un nouveau modèle peut être créé en spécifiant le schéma, le nom de la table et la classe de modèle de la source de déviation. La source est la suivante. Il convient de noter que, où peuvent être créés pour la fonction, mais sont définis dans le même module et la source de déviation actuelle.

app/models/model.py


def create_model_by_prototype(model_name, schema_name, table_name, prototype):
    import copy

    class Meta:
        pass

    setattr(Meta, "db_table", schema_name + "\".\"" + table_name)
    fields = {}
    for field in prototype._meta.fields:
        fields[field.name] = copy.deepcopy(field)

    attrs = {'__module__': "app.models.models", 'Meta': Meta}
    attrs.update(fields)
    model = type(model_name, (models.Model,), attrs)

    return model

Commentaire

Nous examinerons des exemples d'utilisation spécifiques plus tard et expliquerons brièvement la source.

Mains sur

Maintenant, voyons l'image d'utilisation de la fonction en utilisant la fonction créée par la pratique avec django shell.

Création de modèle et de table à détourner

Ceci est omis car il n'exécute que les makemigrations de Django et migre.

Créer un nouveau schéma

Le schéma de stockage de la nouvelle table était cette fois gênant, je l'ai donc créé en me connectant directement à Postgres. Le nom du schéma est user01.

create schema user01;

Lancer le shell Django

$ python manage.py shell
Python 3.7.6 | packaged by conda-forge | (default, Jun  1 2020, 18:11:50) [MSC v.1916 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.

Importation de module

Ensuite, importez les modules requis pour utiliser la fonction.

from chempre.models.models import Compound
from chempre.models import models 

Création dynamique d'un nouveau modèle

Maintenant, créons un modèle dynamiquement en utilisant la fonction créée. Ici, un modèle appelé Compound est utilisé et une table appelée my_compound avec la même définition est créée dans le schéma user01 créé précédemment.

model= models.create_model_by_prototype("MyCompound", "user01", "my_compound", Compound)

Créer une table

Ensuite, créez une table correspondant à Model. Étant donné que ce modèle n'est pas géré par migration, il sera créé différemment que d'habitude. La procédure est la suivante.

from django.db import connection
with connection.schema_editor() as schema_editor:
     schema_editor.create_model(model)

Cela créera une table dans le schéma user01. Quand je me connecte à Postgres avec psql, il est certainement créé.

Enregistrement des données dans le modèle

Ensuite, enregistrons les données. Comme il était difficile de spécifier le champ, je crée ici un enregistrement avec uniquement le champ de nom défini.

model.objects.create(name='compound name')

Rechercher un modèle

Cherchons et vérifions si la table a été créée.

compound=model.objects.get(id=1)[
print(compound.name)

Si vous êtes enregistré, vous devriez voir la valeur "nom du composant". De plus, lorsque je me connecte à Postgres avec psql, un enregistrement est certainement créé.

en conclusion

J'ai pu réaliser en toute sécurité tout ce que je souhaitais à l'origine. Je veux produire en masse le modèle Gangan de cette manière et profiter de la vie Django. Django a beaucoup de tactiques et beaucoup à retenir, mais il n'a pas la robustesse et la rigidité qui sont typiques de ce type de framework, et il semble qu'il puisse être personnalisé de manière flexible.

Les références

Recommended Posts

Créez dynamiquement des tables dans un schéma avec Django, générez dynamiquement des modèles
Enregistrez plusieurs modèles sous un seul formulaire avec Django
Créer une API avec Django
Créer une page d'accueil avec django
Créer et lister des modèles Django
Créer une fonction d'authentification à l'aide de django-allauth et CustomUser dans Django
Générez dynamiquement des graphiques avec matplotlib et intégrez-les au PDF avec reporlab
Ajouter dynamiquement des champs de formulaire dans Django
API GraphQL utilisant graphene_django dans Django
Créer un téléchargeur de fichiers avec Django
Créer un bot LINE avec Django
[Peut être fait en 10 minutes] Créez rapidement un site Web local avec Django
Créer une API RESTful avec Django Rest Framework
Spécifiez dynamiquement le jeu de requêtes ModelChoiceField dans Django
Créer un écran de mise à jour avec Django Updateview
Création de la première application avec Django startproject
Ajouter dynamiquement des champs aux objets Form avec Django
Démarrez Django dans un environnement virtuel à l'aide de Pipenv
Créer un environnement virtuel avec conda avec Python
Créez un environnement Django avec Vagrant en 5 minutes
Créez un tableau de bord pour les appareils réseau avec Django!
Créer une image avec des caractères avec python (japonais)
Créer une nouvelle page en confluence avec Python
Créez une application Hello World avec un seul fichier avec django
Créer les paramètres initiaux et les applications de personnel dans Django
Configurer un module avec plusieurs fichiers dans Django
Comment créer une API Rest dans Django
Jusqu'à ce que vous créiez une nouvelle application dans Django
Implémentation de la fonction d'authentification dans Django REST Framework à l'aide de djoser