Djongo添加Station对象时触发RecursionError问题求助
Django + Djongo: RecursionError When Adding Station with ForeignKey in Admin Panel
问题背景
在Django管理面板添加Station对象时触发RecursionError,错误提示为"no exception message supplied"。移除Station模型中的ForeignKey关联后错误消失,但业务上必须保留该关联逻辑。
核心报错片段
File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\tokens.py", line 19, in __contains__ return item is not None and (self is item or item[:len(self)] == self) RecursionError: maximum recursion depth exceeded in comparison
模型代码
from djongo import models class City(models.Model): name = models.CharField(max_length=100) class Station(models.Model): name = models.CharField(max_length=100) city = models.ForeignKey(City, on_delete=models.CASCADE) def __str__(self): return self.name class Bus(models.Model): number = models.CharField(max_length=10) stations = models.ManyToManyField(Station) def __str__(self): return self.number
完整报错回溯
Internal Server Error: /admin/bus/station/add/ Traceback (most recent call last): File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\query.py", line 808, in __iter__ yield from iter(self._query) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\query.py", line 167, in __iter__ yield self._align_results(doc) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\query.py", line 269, in _align_results if selected.table == self.left_table: File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\sql_tokens.py", line 133, in table return alias2token[name].table File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\sql_tokens.py", line 133, in table return alias2token[name].table File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\sql_tokens.py", line 133, in table return alias2token[name].table [Previous line repeated 917 more times] File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\sql_tokens.py", line 130, in table name = self.given_table File "C:\Users\Admin\Envs\routemaster\lib\site-packages\djongo\sql2mongo\sql_tokens.py", line 141, in given_table name = self._token.get_real_name() File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 361, in get_real_name return self._get_first_name(dot_idx) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 386, in _get_first_name return token.get_name() File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 355, in get_name return self.get_alias() or self.get_real_name() File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 344, in get_alias _, ws = self.token_next_by(t=T.Whitespace) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 244, in token_next_by return self._token_matching(funcs, idx, end) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 223, in _token_matching if func(token): File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\sql.py", line 242, in <lambda> funcs = lambda tk: imt(tk, i, m, t) File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\utils.py", line 100, in imt elif types and any(token.ttype in ttype for ttype in types): File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\utils.py", line 100, in <genexpr> elif types and any(token.ttype in ttype for ttype in types): File "C:\Users\Admin\Envs\routemaster\lib\site-packages\sqlparse\tokens.py", line 19, in __contains__ return item is not None and (self is item or item[:len(self)] == self) RecursionError: maximum recursion depth exceeded in comparison
问题分析
从回溯信息可以看出,递归触发点在Djongo的sql_tokens.py文件中table属性的getter方法(重复调用alias2token[name].table),最终导致sqlparse库的递归比较溢出。这是Djongo处理ForeignKey关联时的已知兼容性bug,并非你的模型存在循环引用——你的模型关联逻辑是单向的(City→Station→Bus),不存在循环依赖。
解决方案
1. 显式指定ForeignKey的related_name
给Station模型的city字段添加明确的related_name,避免Djongo自动生成的名称引发解析冲突:
class Station(models.Model): name = models.CharField(max_length=100) city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='stations') def __str__(self): return self.name
2. 调整Djongo版本
该递归问题在Djongo的部分版本中已被修复,尝试切换到经过验证的稳定版本:
pip install djongo==1.3.6
3. 自定义Admin表单简化查询
修改StationAdmin类,限制Admin加载的字段或优化查询逻辑,避免触发Djongo的bug:
from django.contrib import admin from .models import Station class StationAdmin(admin.ModelAdmin): fields = ('name', 'city') # 仅显示必要字段,减少自动查询 def get_queryset(self, request): # 提前预加载关联的City对象,简化查询结构 return super().get_queryset(request).select_related('city') admin.site.register(Station, StationAdmin)
4. 临时通过Shell创建对象
如果需要紧急创建Station对象,可以绕过Admin面板,直接通过Django Shell操作:
python manage.py shell
from myapp.models import City, Station # 假设已存在名为"Beijing"的City对象 city = City.objects.get(name='Beijing') Station.objects.create(name='Central Station', city=city)
内容的提问来源于stack exchange,提问作者ClawX69
相关产品推荐
相关产品推荐

