web-dev-qa-db-fra.com

Fractionner models.py en plusieurs fichiers

J'essaie de scinder le models.py de mon application en plusieurs fichiers:

Ma première hypothèse était de faire ceci:

myproject/
    settings.py
    manage.py
    urls.py
    __init__.py
    app1/
        views.py
        __init__.py
        models/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models/
            __init__.py
            model3.py
            model4.py

Cela ne fonctionne pas, alors j'ai trouvé ceci , mais dans cette solution j'ai toujours un problème, quand je lance python manage.py sqlall app1 j'ai quelque chose comme:

BEGIN;
CREATE TABLE "product_product" (
    "id" serial NOT NULL PRIMARY KEY,
    "store_id" integer NOT NULL
)
;
-- The following references should be added but depend on non-existent tables:
-- ALTER TABLE "product_product" ADD CONSTRAINT "store_id_refs_id_3e117eef" FOREIGN KEY     ("store_id") REFERENCES "store_store" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "product_product_store_id" ON "product_product" ("store_id");
COMMIT;

Je n'en suis pas vraiment sûr, mais je suis inquiet à propos de la partie The following references should be added but depend on non-existent tables:

Ceci est mon fichier model1.py:

from Django.db import models

class Store(models.Model):
    class Meta:
        app_label = "store"

Ceci est mon fichier model3.py:

from Django.db import models

from store.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

Et apparemment, ça fonctionne mais j'ai le commentaire dans alter table et si j'essaie cela, la même chose se produit:

class Product(models.Model):
    store = models.ForeignKey('store.Store')
    class Meta:
        app_label = "product"

Alors, devrais-je lancer le changement pour les références manuellement? cela peut m'apporter des problèmes avec le sud?

64
diegueus9

Je ne peux même pas commencer à imaginer pourquoi vous voudriez faire cela. Mais je suppose que vous avez une bonne raison. Si j'avais besoin de le faire pour une raison quelconque, je procéderais comme suit:

myproject/
    ...
    app1/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model3.py
            model4.py

Ensuite

#myproject/app1/models.py:
    from submodels/model1.py import *
    from submodels/model2.py import *

#myproject/app2/models.py:
    from submodels/model3.py import *
    from submodels/model4.py import *

Mais si vous n'avez pas de bonne raison, placez model1 et model2 directement dans app1/models.py et model3 et model4 dans app2/models.py.

---deuxième partie---

C'est le fichier app1/submodels/model1.py:

from Django.db import models
class Store(models.Model):
    class Meta:
        app_label = "store"

Corrigez donc votre fichier model3.py:

from Django.db import models
from app1.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

Modifié, au cas où cela se reproduirait pour quelqu'un: Consultez Django-schedule pour voir un exemple de projet qui ne fait que cela . https://github.com/thauber/Django-schedule/tree/master/schedule/modelshttps://github.com/thauber/Django-schedule/

25
Ted

Pour quiconque sur Django 1.9, il est maintenant supporté par le framework sans définir les métadonnées de classe.

https://docs.djangoproject.com/fr/1.9/topics/db/models/#organizing-models-in-a-package

NOTE: Pour Django 2, c'est toujours pareil

La commande manage.py startapp crée une structure d'application qui inclut un fichier models.py. Si vous avez plusieurs modèles, leur organisation dans des fichiers distincts peut être utile.

Pour ce faire, créez un package de modèles. Supprimez models.py et créez un répertoire myapp/models/ avec un fichier __init__.py et les fichiers pour stocker vos modèles. Vous devez importer les modèles dans le fichier __init__.py.

Donc, dans votre cas, pour une structure comme

app1/
    views.py
    __init__.py
    models/
        __init__.py
        model1.py
        model2.py
app2/
    views.py
    __init__.py
    models/
        __init__.py
        model3.py
        model4.py

Il suffit de faire

#myproject/app1/models/__init__.py:
from .model1 import Model1
from .model2 import Model2

#myproject/app2/models/__init__.py:
from .model3 import Model3
from .model4 import Model4

Une note contre l'importation de toutes les classes:

Importer explicitement chaque modèle plutôt que d'utiliser from .models import * présente les avantages de ne pas encombrer l'espace de noms, de rendre le code plus lisible et de conserver les outils d'analyse de code utiles.

97
Vic

En fait, je suis tombé sur un tutoriel sur ce dont vous parlez, vous pouvez le voir ici:

http://paltman.com/breaking-apart-models-in-Django/

Un point clé qui est probablement pertinent: vous pouvez utiliser le champ db_table de la classe Meta pour rediriger les classes déplacées vers leur propre table.

Je peux confirmer que cette approche fonctionne dans Django 1.3

11
Adam Luchjenbroers

Étapes les plus faciles:

  1. Créer un dossier de modèle dans votre application (le nom du dossier doit être modèle )
  2. Supprimer le fichier model.py du répertoire app (sauvegarder le fichier pendant que vous le supprimez)
  3. Et après la création du fichier init . Py dans le dossier du modèle
  4. Et après le fichier init . Py en écriture simple une ligne 
  5. Et après la création du fichier de modèle dans votre dossier de modèle, le nom du fichier de modèle doit être identique à celui du nom de la classe. si le nom de la classe est 'Employee', le nom du fichier de modèle doit ressembler à 'employee.py'
  6. Et ensuite, dans le fichier de modèle, définissez votre table de base de données de la même manière que write, comme dans model.py file
  7. Sauvegarde le

Mon code: de Django_adminlte.models.employee import Employee

Pour votre: from app_name . Models. model_file_nom_fichier_seulement import Nom_classe_which_define_in_model_file


__init__.py

from Django_adminlte.models.employee import Employee

model/employee.py (employee is separate model file)

from Django.db import models

class Employee(models.Model):
eid = models.CharField(max_length=20)
ename = models.CharField(max_length=20)
eemail = models.EmailField()
econtact = models.CharField(max_length=15)

class Meta:
    db_table = "employee"
    # app_label = 'Django_adminlte'

def __str__(self):
    return self.ename
0
Parth Jani