Django - Problema di importazione del modello circolare


116

Non lo capisco davvero, quindi se qualcuno potesse spiegare come funziona lo apprezzerei molto. Ho due applicazioni, Account e Tema ... ecco il mio elenco di impostazioni:

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

Negli account, sto cercando di fare questo:

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)

E nel mio modello a tema:

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 sta eliminando il seguente errore:

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

È una specie di problema di importazione circolare? Ho provato a usare un riferimento pigro, ma nemmeno quello sembra funzionare!


1
Sembra un problema con le importazioni circolari. Perché è necessario importare Accountdal modulo in cui Themeè definito?
Dominic Rodger

Spiacenti, non ho incollato correttamente il mio modello Temi, ho aggiornato il mio post. Lo sto usando nella classe del foglio di stile.
Hanpan

Risposte:


213

Rimuovere l'importazione di Themee utilizzare invece il nome del modello come stringa.

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

5
In realtà deve essere così 'themes.Theme', dato che si trova in un'app diversa.
Daniel Roseman

Ahh, ha funzionato, stavo provando solo "Theme" prima e non ha funzionato. Grazie. C'è qualche tipo di prestazione che colpisce per farlo in questo modo? Mi piacerebbe mantenere le mie ricerche non pigre, se possibile :)
Hanpan

@ Daniel: aggiornato. @ Hanpan: piccolo, sì. Ma solo una volta.
Ignacio Vazquez-Abrams

56

Fino a Django 1.7:

Usa la get_modelfunzione da django.db.modelscui è progettato per l'importazione di modelli pigri .:

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

Nel tuo caso:

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

Ora puoi usare Theme

Per Django 1.7+:

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

10
Usa apps.get_model(app_label, model_name)o apps.get_model('app_label.model_name') in Django 1.7+
phoibos

51

Qualcosa che non ho visto menzionato da nessuna parte in modo sufficientemente dettagliato è come formulare correttamente la stringa all'interno di ForeignKey quando si fa riferimento a un modello in un'app diversa. Questa stringa deve essere app_label.model_name. E, cosa molto importante, app_labelnon è l'intera linea in INSTALLED_APPS, ma solo l'ultimo componente di esso. Quindi, se il tuo INSTALLED_APPS ha questo aspetto:

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

quindi per includere una ForeignKey a un modello in app2 in un modello app1, devi fare:

app2_themodel = ForeignKey('app2.TheModel')

Ho passato parecchio tempo cercando di risolvere un problema di importazione circolare (quindi non potevo semplicemente from another.path.to.app2.models import TheModel) prima di imbattermi in questo, google / SO non è stato di aiuto (tutti gli esempi avevano percorsi di app a componente singolo), quindi spero che questo possa aiutare altri neofiti di django.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.