You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cursor.execute()执行SQL查询时提示“No Such Table”错误,但Customer.objects.raw()可正常运行的原因排查

Django原生cursor查询与objects.raw()的差异问题

最近我在Django项目里遇到了一个特别费解的数据库查询问题,折腾半天还是没搞透,来请教下各位:

问题情况

我尝试用两种方式查询customers表,结果一个报错一个完全正常,具体细节如下:

报错的cursor直接查询代码

这段代码每次运行都会抛出Operational Error: No Such Table customers:

cursor = connection.cursor()
cursor.execute("SELECT * FROM customers") 
r = cursor.fetchone()
print(r)

正常运行的objects.raw()查询代码

但用Django模型的raw()方法执行完全相同的SQL语句,却能正常获取结果:

sql = "SELECT * FROM customers"
customer = Customer.objects.raw(sql)[:10]
print(customer)
print(connection.queries)

通过debug_toolbar查看执行日志,确认这段代码确实正确命中了目标数据库:

Executed SQL SELECT * FROM customers
Time 1.1129379272460938 ms
Database network_db

额外的奇怪现象

按照Django官方文档的说法,表名应该是应用名_表名的格式,但我尝试把SQL改成SELECT * FROM network_customers时,反而会报错no such table: network_customers,去掉应用名前缀才能正常运行。

我的项目配置信息

数据库配置(settings.py)

DATABASES = {
 'default':{
 'ENGINE': 'django.db.backends.sqlite3',
 'NAME': BASE_DIR / 'db.sqlite3',
 },
 'network_db':{
 'ENGINE': 'django.db.backends.sqlite3',
 'NAME': BASE_DIR / 'Network.sqlite3',
 },
 'simulation_db':{
 'ENGINE': 'django.db.backends.sqlite3',
 'NAME': BASE_DIR / 'Simulation.sqlite3',
 }
}

Network应用的apps.py

from django.apps import AppConfig
class NetworkConfig(AppConfig):
 default_auto_field = 'django.db.models.BigAutoField'
 name = 'network'

我已经通过debug_toolbar确认BASE_DIR路径完全正确,数据库文件位置没有问题,而且用原生sqlite3直接连接文件的方式也能查到数据:

database='C:/EXACTLOCATION/../../Network.sqlite3'
db=sqlite3.connect(database)
c=db.cursor()
sql_command='SELECT * FROM customers'
customer = c.execute(sql_command)
customer = c.fetchall()

我的核心疑问

  1. 为什么用objects.raw()能正常查询,但直接用connection.cursor()就找不到表?
  2. 为什么不需要按照文档要求添加network_前缀就能查到表?

问题原因解答

1. 数据库连接的指向差异

你直接调用connection.cursor()时,默认使用的是settings里的default数据库(也就是db.sqlite3),但你的customers表实际上是存在network_db对应的Network.sqlite3文件里的!

而Customer.objects.raw()能正常工作,是因为Customer模型属于network应用,Django会自动关联该模型对应的数据库(要么是模型里配置了using参数,要么是项目通过路由/应用配置默认让network应用使用network_db)。

你可以直接验证这个点,修改报错的代码,明确指定使用network_db的连接:

from django.db import connections
# 明确指定用network_db的数据库连接
cursor = connections['network_db'].cursor()
cursor.execute("SELECT * FROM customers")
r = cursor.fetchone()
print(r)

这样应该就能正常获取到数据了。

2. 表名前缀消失的原因

通常Django会自动给表名加上应用名前缀,但如果你的Customer模型里显式配置了db_table参数,比如:

class Customer(models.Model):
    # 你的字段定义
    class Meta:
        db_table = 'customers'  # 直接指定表名为customers

那Django就不会自动添加network_前缀了,这就是为什么你用network_customers会找不到表,而直接用customers可以成功查询的原因。你可以去检查下Customer模型的Meta类是不是有这个配置。


内容的提问来源于stack exchange,提问作者RedRum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 21:17:33