Django - Dairesel model içe aktarma sorunu


116

Bunu gerçekten anlamıyorum, bu yüzden birisi bunun nasıl çalıştığını açıklayabilirse çok memnun olurum. İki uygulamam var, Hesaplar ve Tema ... işte ayarlar listem:

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

Hesaplarda şunu yapmaya çalışıyorum:

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)

Ve tema modelimde:

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 aşağıdaki hatayı veriyor:

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

Bu bir çeşit dairesel ithalat sorunu mu? Tembel bir referans kullanmayı denedim ama bu da işe yaramıyor gibi görünüyor!


1
Döngüsel ithalatla ilgili bir sorun gibi görünüyor. Neden tanımlı Accountmodülden içe aktarmanız gerekiyor Theme?
Dominic Rodger

Üzgünüm, Temalar modelimi doğru yapıştırmadım, yazımı güncelledim. Bunu Stil Sayfası sınıfında kullanıyorum.
Hanpan

Yanıtlar:


213

İçe aktarmayı kaldırın ve Themebunun yerine model adını bir dize olarak kullanın.

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

5
Aslında 'themes.Theme'farklı bir uygulamada olduğu gibi olması gerekiyor .
Daniel Roseman

Ahh, bu işe yaradı, daha önce sadece 'Tema'yı deniyordum ve işe yaramadı. Teşekkürler. Bunu bu şekilde yapmak için herhangi bir performans artışı var mı? Mümkünse aramalarımı tembel tutmak istiyorum :)
Hanpan

@Daniel: Güncellendi. @Hanpan: Küçük bir tane, evet. Ama sadece bir kez.
Ignacio Vazquez-Abrams

56

Django 1.7'ye kadar:

Geç model ithalatı için tasarlanan get_modelişlevi kullanın . django.db.models:

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

Senin durumunda:

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

Şimdi kullanabilirsin Theme

Django 1.7+ için:

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

10
Kullanım apps.get_model(app_label, model_name)veya apps.get_model('app_label.model_name') Django 1.7+ yılında
Phoibos

51

Herhangi bir yerde yeterince ayrıntılı olarak bahsetmediğim bir şey, farklı bir uygulamadaki bir modele atıfta bulunurken ForeignKey içindeki dizenin nasıl düzgün bir şekilde formüle edileceğidir. Bu dizenin olması gerekiyor app_label.model_name. Ve çok daha önemlisi, app_labelINSTALLED_APPS'deki tüm satır değil, yalnızca son bileşenidir . Dolayısıyla, INSTALLED_APPS'niz şöyle görünüyorsa:

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

daha sonra bir app1 modelindeki app2'deki bir modele bir ForeignKey eklemek için şunları yapmanız gerekir:

app2_themodel = ForeignKey('app2.TheModel')

Dairesel bir içe aktarma sorununu çözmeye çalışırken oldukça uzun bir süre harcadım (bu yüzden sadece yapamadım from another.path.to.app2.models import TheModel), buna rastlamadan önce, google / SO yardımcı olmadı (tüm örneklerde tek bileşenli uygulama yolları vardı), bu yüzden umarım bu diğerlerine yardımcı olur django yeni başlayanlar.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.