Django - питання імпорту кругової моделі


116

Я справді цього не отримую, тому, якщо хтось міг би пояснити, як це працює, я дуже вдячний. У мене є дві програми, Облікові записи та Тема ... ось мій список налаштувань:

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

В облікових записах я намагаюся це зробити:

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)

І в моїй тематичній моделі:

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 видаляє таку помилку:

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

Це якась кругова проблема імпорту? Я спробував використовувати ледачу посилання, але це, здається, не працює!


1
Це схоже на проблему кругового імпорту. Чому потрібно імпортувати Accountз модуля, де Themeвизначено?
Домінік Роджер

Вибачте, я неправильно вставив свою тему, я оновив свою публікацію. Я використовую його в класі Stylesheet.
Ганпан

Відповіді:


213

Видаліть імпорт Themeі замість цього використовуйте ім'я моделі як рядок.

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

5
Насправді це має бути 'themes.Theme', як це є в іншому додатку.
Даніель Роузман

Ах, це спрацювало, я раніше пробував просто "Тему", і це не вийшло. Дякую. Чи є якийсь хіт виступу, щоб зробити це таким чином? Я б хотів, щоб, якщо це можливо,
мої пошуки

@Daniel: оновлено. @Hanpan: Невеликий, так. Але лише один раз.
Ігнасіо Васкес-Абрамс

56

До Джанго 1.7:

Використовуйте get_modelфункцію, з django.db.modelsякої розроблено для лінивого імпорту моделі:

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

У вашому випадку:

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

Тепер ви можете використовувати Theme

Для Django 1.7+:

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

10
Використовуйте apps.get_model(app_label, model_name)або apps.get_model('app_label.model_name') в Django 1.7+
phoibos

51

Щось я ще ніде не бачив достатньо детально, як правильно сформулювати рядок всередині ForeignKey при посиланні на модель в іншому додатку. Цей рядок повинен бути app_label.model_name. І, що дуже важливо, app_labelце не весь рядок в INSTALLED_APPS, а лише останній його компонент . Тож якщо ваш INSTALLED_APPS виглядає так:

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

потім, щоб включити ForeignKey до моделі в app2 до моделі app1, потрібно зробити:

app2_themodel = ForeignKey('app2.TheModel')

Я витратив досить тривалий час, намагаючись вирішити проблему кругового імпорту (тому я не міг просто from another.path.to.app2.models import TheModel), перш ніж натрапив на це, google / SO не допомогла (усі приклади мали однокомпонентні шляхи до програми), тому, сподіваємось, це допоможе іншим новачки джанго.


40

Оскільки Django 1.7 правильний шлях - це так:

from django.apps import apps

YourModel = apps.get_model('your_app_name', 'YourModel')

Дивіться: https://docs.djangoproject.com/ja/1.9/ref/applications/#django.apps.apps.get_model


5
Також є синтаксис швидкого доступу з одною аргументацією: apps.get_model('your_app_name.YourModel')зручний для використання в mapтощо.
Тейлор Едмістон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.