SQL Server后端下Django Admin的DjangoQL查询报错:无explain_format属性
问题描述
在Django项目中使用SQL Server作为数据库后端,在Admin页面通过DjangoQL语法(如name = "Test")查询模型数据时触发AttributeError,提示'Query' object has no attribute 'explain_format'。SQLite后端下功能正常,数据库连接无问题(可通过python manage.py shell查询数据),仅Admin查询时报错。
环境配置
数据库配置(settings.py)
DATABASES = { 'default': { 'ENGINE': 'mssql', 'HOST': my_host, 'NAME': my_name, 'OPTIONS': { 'driver': 'ODBC Driver 17 for SQL Server', 'host_is_server': True, } } }
模型代码(main/models.py)
from django.db import models class MyModel(models.Model): name = models.CharField(blank=False, max_length=255) class Meta: constraints = [ models.UniqueConstraint( fields=['name'], condition=models.Q(name__isnull=False), name='non_null_name_unique', ), ]
Admin配置(main/admin.py)
from django.contrib import admin from djangoql.admin import DjangoQLSearchMixin class MyModelAdmin(DjangoQLSearchMixin, admin.ModelAdmin): search_fields = ['name'] list_display = ['name'] admin.site.register(MyModel, MyModelAdmin)
环境信息
- Django版本:4.2.15
- Python版本:3.10.11
- 依赖库:djangoql、mssql-django、pymssql
异常信息
/admin/main/mymodel/处触发AttributeError:'Query' object has no attribute 'explain_format'
解决方案
该问题源于djangoql库执行查询时调用了QuerySet的explain()方法,但mssql-django提供的SQL Server后端Query类未实现explain_format属性(该属性在Django内置的SQLite、PostgreSQL等后端中存在),导致触发属性错误。以下是两种解决方式:
方法1:临时修改djangoql源码
找到djangoql库中调用explain()的代码(通常在djangoql/compiler.py或djangoql/admin.py中),添加SQL Server后端判断,跳过explain操作:
# 找到原有代码块 if queryset.query.explain_format is not None: # 执行explain相关逻辑 # 修改为: from django.db import connections db_engine = connections[queryset.db].settings_dict['ENGINE'] if db_engine != 'mssql' and queryset.query.explain_format is not None: # 执行explain相关逻辑
方法2:自定义SQL Server Query类(推荐)
通过自定义Query类添加explain_format属性,覆盖mssql-django的默认实现:
- 在项目中创建
db/backends/mssql/query.py文件:
from mssql.django.backend.query import Query as MSSQLQuery class Query(MSSQLQuery): @property def explain_format(self): # 返回None或SQL Server支持的格式 return None
- 创建
db/backends/mssql/base.py文件:
from mssql.django.backend.base import DatabaseWrapper as MSSQLDatabaseWrapper from .query import Query class DatabaseWrapper(MSSQLDatabaseWrapper): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.query_class = Query
- 修改settings.py中的数据库ENGINE配置:
DATABASES = { 'default': { 'ENGINE': 'db.backends.mssql', # 替换为自定义后端路径 'HOST': my_host, 'NAME': my_name, 'OPTIONS': { 'driver': 'ODBC Driver 17 for SQL Server', 'host_is_server': True, } } }
内容的提问来源于stack exchange,提问作者evan54
相关产品推荐
相关产品推荐

