【问题标题】:Circular importing error using wagtail-generic-chooser使用 wagtail-generic-chooser 循环导入错误
【发布时间】:2020-03-29 05:08:42
【问题描述】:

我正在使用 wagtails wagtail-generic-chooser 为我的数据模型创建 customChoosers,每当我引用其他 modelAdmin 模型时,它都可以正常工作。

但是,我遇到了这样一种情况,即我有一个 Lexis 模型,其中一个字段具有指向自身的 FK 链接。这个想法是有一个词汇术语,然后可以有相关的词汇术语与之相关联。它适用于普通的 FieldPanel,但当有数百个词汇术语时,这不是一个很好的 UI 体验。因此,我想为此字段创建一个自定义 LexisChooser。但是,我遇到的问题是根据文档来创建功能小部件,我需要创建一个视图和 adminChooser 来引用选择器面板连接到的模型。

https://github.com/wagtail/wagtail-generic-chooser#chooser-widgets-model-based

这是有道理的,但是,当我尝试将 LexisChooser 导入我的 Lexis 模型以将 LexisChooser 用作小部件时,我收到以下错误。

ImportError: 无法从“lexis.models”导入名称“Lexis”

我意识到这是由于循环导入错误问题,因为我有子类正在导入 Lexis 类以构建 LexisChooser 小部件,然后我尝试将该小部件导入 Lexis 类。

我知道这不是 Wagtail 的错误,也不是 wagtail-generic-chooser 的问题,但是,有没有人知道如何重构代码以实现此功能,以便我可以使用 LexisChooser Lexis 模型的一个字段。

下面是我的代码。

views.py 创建视图

from django.utils.translation import ugettext_lazy as _
from generic_chooser.views import ModelChooserViewSet
from lexis.models import Lexis

class LexisChooserViewSet(ModelChooserViewSet):

    icon = 'user'
    model = Lexis
    page_title = _("Choose A Lexis Term")
    per_page = 20
    order_by = 'term'
    fields = ['term']

wagtail_hooks.py 注册视图

from wagtail.core import hooks
from .views import LexisChooserViewSet

@hooks.register('register_admin_viewset')
def register_lexis_chooser_viewset():
    return LexisChooserViewSet('lexis_chooser', url_prefix='lexis-chooser')

widgets.py 创建一个小部件

from django.utils.translation import ugettext_lazy as _
from generic_chooser.widgets import AdminChooser
from lexis.models import Lexis

class LexisChooser(AdminChooser):

     choose_one_text = _('Choose a Lexis')
     choose_another_text = _('Choose another Lexis')
     link_to_chosen_text = _('Edit this Lexis')
     model = Lexis
     choose_modal_url_name = 'lexis_chooser:choose'

lexis/models.py 使用小部件

from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel
from wagtail.core.models import Orderable
from modelcluster.models import ClusterableModel
from chooser_panels.widgets import LexisChooser


# Orderable link to multiple other linked lexis terms
class LexisLink(Orderable):

    page = ParentalKey("lexis.Lexis", related_name="lexis_link")

    term_link = models.ForeignKey(
        'lexis.Lexis', 
        on_delete=models.SET_NULL, 
        related_name='term_linked', 
        null=True
    )

    panels = [
        FieldPanel("term_link", widget=LexisChooser)
    ]


class Lexis(ClusterableModel):

    template = "lexis/lexis_page.html"
    term = models.CharField(max_length=100, blank=True, null=True)
    panels = [
        FieldPanel("term"),
        InlinePanel('lexis_link', label='Linked Lexis Terms'), 
    ]

    def __str__(self):
        return self.term

    class Meta:
        verbose_name = "Lexis"
        verbose_name_plural = "Lexis"

不幸的是,这会导致循环导入错误: ImportError:无法从“lexis.models”导入名称“Lexis”

在研究此错误时,我发现人们建议根据需要在类中而不是在每个文件的顶部导入 Lexis,但这似乎不适用于上述子类化,因为我得到了同样的错误.

如果您对我如何重构代码以使其正常工作而不产生循环导入错误有任何想法,我们将不胜感激。

我在跑步 姜戈 3, 蟒蛇3.7, 鹡鸰 2.8

谢谢

【问题讨论】:

    标签: python django python-3.x importerror wagtail


    【解决方案1】:

    将您的模型文件拆分为两个单独的文件,其中包含LexisLexisLinkas demonstrated in the documentation.

    然后LexisLink 可以引用LexisChooser,而它干净地引用Lexis 模型。

    【讨论】:

    • 太棒了!谢谢@OregonTrail!我试图赞成你的回答,但因为我是 StackOverflow 的新手,所以他们直到我得到 15 票或其他东西才会计算它。我对您的解决方案的一个问题是,由于修复了命名空间问题,这项工作是否有效?通过使用 init.py 是否可以保持命名空间干净,从而没有冲突?
    • 嗯,不是真的。它起作用的原因很简单,就是没有循环引用,因此没有依赖于执行顺序的行为。 __init__.py 始终存在并为每个作为目录的 python 模块执行。您可以通过单击复选标记来接受我的回答:)
    猜你喜欢
    • 2020-07-09
    • 1970-01-01
    • 2016-12-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 2019-03-09
    相关资源
    最近更新 更多