Django-Tables2-Column-Shifter获取表类时触发frozen importlib错误
问题描述
我在Django项目的app1中已成功使用Django-Tables2-Column-Shifter库,在另一个使用独立模型的应用app2中复用相同逻辑调用该库时抛出异常,报错信息如下:
File "/home/datavizapp/.virtualenvs/venv/lib/python3.9/site-packages/django/utils/module_loading.py", line 17, in import_string module = import_module(module_path) File "/usr/local/lib/python3.9/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1030, in _gcd_import File "<frozen importlib._bootstrap>", line 1007, in _find_and_load File "<frozen importlib._bootstrap>", line 972, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed File "<frozen importlib._bootstrap>", line 1030, in _gcd_import File "<frozen importlib._bootstrap>", line 1007, in _find_and_load File "<frozen importlib._bootstrap>", line 984, in _find_and_load_unlocked ModuleNotFoundError: No module named 'mysite'
其余代码逻辑均可正常运行,仅替换get_table_class相关逻辑时触发报错:
- 正常运行代码:
tabledata_table = get_table_1_class( self.table_class_version )(tabledata_queryset)
- 触发报错代码:
tabledata_table = get_table_2_class( self.table_class_version )(tabledata_queryset)
相关代码
app2/views.py
from project_name.app1.models import Table1 from project_name.app2.models import Table2 from project_name.app2.tables import get_table_1_class from project_name.app2.tables import get_table_2_class #from project_name.app1.tables import get_table_1_class # 取消注释后可正常运行(原代码位于app1中) from django_tables2_column_shifter.tables import ( ColumnShiftTableBootstrap4 ) from django.contrib.auth import get_user_model User = get_user_model() from django.views.generic import TemplateView from django_tables2.config import RequestConfig class Base(object): container_css = "span10 offset1" template_name = "cryptoscreener/shifter-template.html" table_class_version = ColumnShiftTableBootstrap4 def get_context_data(self, **kwargs): context = super(Base, self).get_context_data(**kwargs) # 构建表 tabledata_queryset = Table1.objects.all() #tabledata_queryset = Table2.objects.all() # 该行代码可正常运行 # 下方为报错触发位置,当前代码可正常运行,替换为get_table_2_class即触发报错 tabledata_table = get_table_1_class( self.table_class_version )(tabledata_queryset) # 开启排序与分页 RequestConfig(self.request, paginate={'per_page': 20}).configure(tabledata_table) context['container_css'] = self.container_css context['tabledata_table'] = tabledata_table context['tabledata_queryset'] = tabledata_queryset class Bootstrap5(Base, TemplateView): container_css = "col-xs-10 col-xs-offset-1" template_name = "cryptoscreener/shifter-template.html" table_class_version = ColumnShiftTableBootstrap4
app2/tables.py
from project_name.app1.models import Table1 def get_table_1_class(TableClass): class Table1Class(TableClass): class Meta: model = Table1 return Table2Class # 从app2的views.py调用get_table_2_class时出现报错 from project_name.app2.models import Table2 def get_table_2_class(TableClass): class Table2Class(TableClass): class Meta: model = Table2 return Table2Class
模板文件 shifter-template.html
{% load static %} {% load django_tables2 %} {% load render_table from django_tables2 %} <!DOCTYPE html> {% load static %} <html lang="{{ LANGUAGE_CODE|default:"en" }}"> <head> <title>Testproject</title> <meta charset="utf-8"> <meta name="description" content="Testproject for django-tables2-column-shifter"> <meta name="author" content="Grzegorz Tężycki"> {# bootstrap样式 #} {% block bootstrap_css %} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> {% endblock %} {% block extra_head %}{% endblock extra_head %} <style> body { width : 90%; margin: 0 auto; } </style> </head> <body> {% render_table tabledata_table %} {% block body_ekstra %} {# bootstrap脚本 #} {% block bootstrap_js %} {% endblock %} {# !! --> column_shifter依赖JS #} <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.3/dist/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script type="text/javascript" src="{% static 'django_tables2_column_shifter/js/django_tables2_column_shifter.min.js' %}"></script> {% endblock body_ekstra %} </body> </html>
settings.py 中 INSTALLED_APPS 配置
# APPS # ------------------------------------------------------------------------------ DJANGO_APPS = [ "rest_framework", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.sites", "django.contrib.messages", "django.contrib.staticfiles", # "django.contrib.humanize", # 实用模板标签 "django.contrib.admin", "django.forms", ] THIRD_PARTY_APPS = [ "crispy_forms", "allauth", "allauth.account", "allauth.socialaccount", "allauth.socialaccount.providers.google", "django_tables2", "django_tables2_column_shifter", "bootstrap4", "django_filters", "stripe", # 支付用stripe "annoying", # django-annoying "tailwind", # tailwind css "widget_tweaks", ] LOCAL_APPS = [ "project_name.users.apps.UsersConfig", # 自定义应用在此处添加 "project_name.app1.apps.App1Config", "project_name.app2.apps.App2Config", "theme", # tailwind css 相关 ] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
项目结构

排查思路与修复方案
首先修正代码里的明确笔误:app2/tables.py中get_table_1_class函数内定义的类为Table1Class,但返回值写的是Table2Class,属于低级拼写错误。
核心报错ModuleNotFoundError: No module named 'mysite'由两个原因共同导致:
- 函数内部动态定义的表类默认
__module__属性解析异常,django-tables2-column-shifter内部做动态类导入时,错误拼接了不存在的mysite前缀路径 - 项目中残留旧的
mysite项目名配置引用,路径解析时命中了无效值
按以下步骤修复即可:
- 重写
app2/tables.py,修正返回值笔误,同时给动态生成的表类显式指定正确的__module__属性,避免第三方库做路径解析时出错:
from project_name.app1.models import Table1 from project_name.app2.models import Table2 def get_table_1_class(TableClass): class Table1Class(TableClass): class Meta: model = Table1 # 显式绑定类所属模块路径 Table1Class.__module__ = "project_name.app2.tables" return Table1Class def get_table_2_class(TableClass): class Table2Class(TableClass): class Meta: model = Table2 Table2Class.__module__ = "project_name.app2.tables" return Table2Class
- 全局搜索项目代码,检查
manage.py、wsgi.py、asgi.py中的DJANGO_SETTINGS_MODULE配置,确认指向project_name.settings,清理所有残留的mysite字符串引用 - 清理项目缓存与编译文件后重启服务:
find . -name "*.pyc" -delete find . -name "__pycache__" -type d -exec rm -rf {} +
内容的提问来源于stack exchange,提问作者Billy Haskell
相关产品推荐
相关产品推荐

