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.