Django - Problem beim Import von kreisförmigen Modellen


115

Ich verstehe das wirklich nicht. Wenn also jemand erklären könnte, wie das funktioniert, würde ich es sehr schätzen. Ich habe zwei Anwendungen, Konten und Thema ... hier ist meine Einstellungsliste:

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

In Konten versuche ich Folgendes:

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)

Und in meinem Themenmodell:

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 wirft den folgenden Fehler aus:

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

Ist dies eine Art zirkuläres Importproblem? Ich habe versucht, eine faule Referenz zu verwenden, aber das scheint auch nicht zu funktionieren!


1
Es sieht nach einem Problem mit zirkulären Importen aus. Warum müssen Sie Accountaus dem Modul importieren, in dem Themees definiert ist?
Dominic Rodger

Entschuldigung, ich habe mein Themes-Modell nicht richtig eingefügt. Ich habe meinen Beitrag aktualisiert. Ich benutze es in der Stylesheet-Klasse.
Hanpan

Antworten:


211

Entfernen Sie den Import von Themeund verwenden Sie stattdessen den Modellnamen als Zeichenfolge.

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

5
Eigentlich muss das so sein 'themes.Theme', wie es in einer anderen App ist.
Daniel Roseman

Ahh, das hat funktioniert, ich habe vorher nur 'Theme' ausprobiert und es hat nicht funktioniert. Vielen Dank. Gibt es einen Performance-Hit dafür? Ich möchte meine Lookups wenn möglich nicht faul halten :)
Hanpan

@ Daniel: Aktualisiert. @ Hanpan: Ein kleiner, ja. Aber nur einmal.
Ignacio Vazquez-Abrams

56

Bis zu Django 1.7:

Verwenden Sie eine get_modelFunktion, django.db.modelsdie für verzögerte Modellimporte ausgelegt ist:

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

In deinem Fall:

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

Jetzt können Sie verwenden Theme

Für Django 1.7+:

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

10
Verwendung apps.get_model(app_label, model_name)oder apps.get_model('app_label.model_name') in Django 1.7+
Phoibos

51

Etwas, das ich nirgends ausführlich genug erwähnt habe, ist die korrekte Formulierung der Zeichenfolge in ForeignKey, wenn auf ein Modell in einer anderen App verwiesen wird. Diese Zeichenfolge muss sein app_label.model_name. Und vor allem ist das app_labelnicht die gesamte Zeile in INSTALLED_APPS, sondern nur die letzte Komponente davon. Wenn Ihr INSTALLED_APPS also so aussieht:

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

Um einen ForeignKey in ein Modell in App2 in einem App1-Modell aufzunehmen, müssen Sie Folgendes tun:

app2_themodel = ForeignKey('app2.TheModel')

Ich habe ziemlich lange versucht, ein Problem mit dem zirkulären Import zu lösen (also konnte ich es nicht einfach from another.path.to.app2.models import TheModel), bevor ich darauf gestoßen bin. Google / SO war keine Hilfe (alle Beispiele hatten Einzelkomponenten-App-Pfade). Hoffentlich hilft dies anderen Django-Neulinge.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.