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กำหนดไว้
Dominic Rodger

ขออภัยฉันวางโมเดลธีมไม่ถูกต้องฉันได้อัปเดตโพสต์แล้ว ฉันใช้มันในคลาสสไตล์ชีต
Hanpan

คำตอบ:


213

ลบการนำเข้าThemeและใช้ชื่อรุ่นเป็นสตริงแทน

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

5
ที่จริงแล้วต้อง'themes.Theme'เป็นเพราะอยู่ในแอปอื่น
Daniel Roseman

อ่าได้ผลฉันลองใช้แค่ 'Theme' ก่อนหน้านี้แล้วก็ไม่ได้ผล ขอบคุณ มีประสิทธิภาพการทำงานแบบใดบ้างที่ทำด้วยวิธีนี้? ฉันต้องการให้การค้นหาของฉันไม่ขี้เกียจถ้าเป็นไปได้ :)
Hanpan

@ แดเนียล: อัพเดท @ ฮันปาน: ตัวเล็กใช่มะ แต่เพียงครั้งเดียว.
Ignacio Vazquez-Abrams

56

ไม่เกิน Django 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
Use apps.get_model(app_label, model_name)or apps.get_model('app_label.model_name') in Django
1.7+

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 ก็ไม่ช่วยอะไร (ตัวอย่างทั้งหมดมีเส้นทางแอปส่วนประกอบเดียว) ดังนั้นหวังว่าสิ่งนี้จะช่วยคนอื่น ๆ มือใหม่ django.


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
นอกจากนี้ยังมีไวยากรณ์ทางลัดแบบ single-arg: apps.get_model('your_app_name.YourModel')สะดวกสำหรับการใช้งานในรูปแบบmapอื่น ๆ
Taylor Edmiston
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.