Django - problem z importem modelu kołowego


116

Naprawdę tego nie rozumiem, więc gdyby ktoś mógł wyjaśnić, jak to działa, byłbym bardzo wdzięczny. Mam dwie aplikacje, konta i motyw ... oto moja lista ustawień:

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

Na kontach próbuję to zrobić:

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)

A w moim modelu motywu:

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 wyrzuca następujący błąd:

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

Czy to jakiś problem z importem w obiegu zamkniętym? Próbowałem użyć leniwego odniesienia, ale to też nie działa!


1
Wygląda to na problem z importem cyklicznym. Dlaczego musisz importować Accountz modułu, w którym Themejest zdefiniowane?
Dominic Rodger,

Przepraszamy, nie wkleiłem poprawnie modelu Motywy, zaktualizowałem swój post. Używam go w klasie Stylesheet.
Hanpan,

Odpowiedzi:


213

Usuń import Themei zamiast tego użyj nazwy modelu jako ciągu.

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

5
Właściwie to musi być 'themes.Theme', ponieważ jest w innej aplikacji.
Daniel Roseman,

Ach, to zadziałało, wcześniej próbowałem tylko „Theme” i nie zadziałało. Dzięki. Czy można to zrobić w ten sposób? Chciałbym, aby moje wyszukiwania nie były leniwe, jeśli to możliwe :)
Hanpan, 7-10

@Daniel: Zaktualizowano. @Hanpan: Mały, tak. Ale tylko raz.
Ignacio Vazquez-Abrams,

56

Upto Django 1.7:

Użyj get_modelfunkcji, z django.db.modelsktórej jest przeznaczona do leniwego importu modeli .:

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

W Twoim przypadku:

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

Teraz możesz użyć Theme

Dla Django 1.7+:

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

10
Użyj apps.get_model(app_label, model_name)lub apps.get_model('app_label.model_name') w Django
1.7+

51

Coś, czego nie widziałem, o czym nigdzie nie wspomniałem wystarczająco szczegółowo, to sposób prawidłowego sformułowania ciągu wewnątrz ForeignKey podczas odwoływania się do modelu w innej aplikacji. Ten ciąg musi być app_label.model_name. I, co bardzo ważne, app_labelnie jest to cała linia w INSTALLED_APPS, ale tylko jej ostatni składnik . Więc jeśli Twoje INSTALLED_APPS wygląda tak:

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

następnie aby dołączyć klucz obcy do modelu w app2 w modelu app1, należy wykonać:

app2_themodel = ForeignKey('app2.TheModel')

Spędziłem sporo czasu próbując rozwiązać problem z importem cyklicznym (więc nie mogłem po prostu from another.path.to.app2.models import TheModel), zanim natknąłem się na to, Google / SO nie pomogło (wszystkie przykłady miały ścieżki aplikacji z jednym komponentem), więc mam nadzieję, że pomoże to innym nowicjusze django.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.