Django - Problème d'importation de modèle circulaire


116

Je ne comprends vraiment pas cela, donc si quelqu'un pouvait expliquer comment cela fonctionne, je l'apprécierais beaucoup. J'ai deux applications, Comptes et Thème ... voici ma liste de paramètres:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'accounts',
    'themes',
)

Dans les comptes, j'essaye de faire ceci:

from themes.models import Theme

class Account(models.Model):
    ACTIVE_STATUS = 1
    DEACTIVE_STATUS = 2
    ARCHIVE_STATUS = 3
    STATUS_CHOICES = (
        (ACTIVE_STATUS, ('Active')),
        (DEACTIVE_STATUS, ('Deactive')),
        (ARCHIVE_STATUS, ('Archived')),
    )

    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=250)
    slug = models.SlugField(unique=True, verbose_name='URL Slug')
    status = models.IntegerField(choices=STATUS_CHOICES, default=ACTIVE_STATUS, max_length=1)
    owner = models.ForeignKey(User)
    enable_comments = models.BooleanField(default=True)
    theme = models.ForeignKey(Theme)
    date_created = models.DateTimeField(default=datetime.now)

Et dans mon modèle de thème:

class Theme(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=250)
    slug = models.SlugField(unique=True, verbose_name='URL Slug')
    date_created = models.DateTimeField(default=datetime.now)

class Stylesheet(models.Model):
    id = models.AutoField(primary_key=True)
    account = models.ForeignKey(Account)
    date_created = models.DateTimeField(default=datetime.now)
    content = models.TextField()

Django supprime l'erreur suivante:

from themes.models import Theme
ImportError: cannot import name Theme

S'agit-il d'une sorte de problème d'importation circulaire? J'ai essayé d'utiliser une référence paresseuse, mais cela ne semble pas non plus fonctionner!


1
Cela ressemble à un problème avec les importations circulaires. Pourquoi avez-vous besoin d'importer à Accountpartir du module où Themeest défini?
Dominic Rodger

Désolé, je n'ai pas collé correctement mon modèle de thèmes, j'ai mis à jour mon message. Je l'utilise dans la classe Stylesheet.
Hanpan

Réponses:


213

Supprimez l'importation Themeet utilisez le nom du modèle comme chaîne à la place.

theme = models.ForeignKey('themes.Theme')

5
En fait, cela doit être 'themes.Theme', car c'est dans une application différente.
Daniel Roseman

Ahh, ça a marché, j'essayais juste "Thème" avant et ça n'a pas marché. Merci. Y a-t-il une sorte de succès de performance pour le faire de cette façon? Je voudrais garder mes recherches non paresseuses si possible :)
Hanpan

@Daniel: Mis à jour. @Hanpan: Un petit, oui. Mais une seule fois.
Ignacio Vazquez-Abrams

56

Jusqu'à Django 1.7:

Utilisez la get_modelfonction à partir de django.db.modelslaquelle est conçue pour les importations de modèles paresseux:

from django.db.models import get_model
MyModel = get_model('app_name', 'ModelName')

Dans ton cas:

from django.db.models import get_model
Theme = get_model('themes', 'Theme')

Maintenant vous pouvez utiliser Theme

Pour Django 1.7+:

from django.apps import apps
apps.get_model('app_label.model_name')

10
Utiliser apps.get_model(app_label, model_name)ou apps.get_model('app_label.model_name') dans Django 1.7+
phoibos

51

Quelque chose que je n'ai vu mentionné nulle part avec suffisamment de détails est de savoir comment formuler correctement la chaîne à l'intérieur de ForeignKey lors du référencement d'un modèle dans une application différente. Cette chaîne doit être app_label.model_name. Et, plus important encore, le app_labeln'est pas la ligne entière dans INSTALLED_APPS, mais seulement le dernier composant de celui-ci. Donc, si votre INSTALLED_APPS ressemble à ceci:

INSTALLED_APPS = (
...
    'path.to.app1',
    'another.path.to.app2'
)

puis pour inclure une ForeignKey à un modèle dans app2 dans un modèle app1, vous devez faire:

app2_themodel = ForeignKey('app2.TheModel')

J'ai passé assez de temps à essayer de résoudre un problème d'importation circulaire (donc je ne pouvais pas juste from another.path.to.app2.models import TheModel) avant de tomber dessus, google / SO ne m'aidait pas (tous les exemples avaient des chemins d'application à composant unique), donc j'espère que cela aidera les autres les débutants de django.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.