Django中objects.raw()触发InvalidQuery错误(需含主键)的解决方法
解决Django 1.11的InvalidQuery错误:"Raw query must include the primary key"
先把你遇到的问题场景理清楚:
在请求路径
/crms/cust/cust_popup/触发InvalidQuery错误,提示“Raw query must include the primary key”。请求是POST方法,用的Django 1.11.1、Python 3.4.3,对应的模型是:# models.py class Cu_00(models.Model): cu_code = models.CharField(primary_key=True, unique=True, max_length=50) cu_nm = models.CharField(db_index=True, max_length=100) # 其他字段省略
咱直接说解决方案,这个错误其实就是Django的raw()原生查询机制在搞事情——它要求你用raw()查出来的结果必须包含模型的主键字段(也就是这里的cu_code),这样Django才能把查询结果映射成合法的模型实例。
最直接的修复:给raw查询补上主键字段
先去检查你视图里处理POST请求的代码,找到用Cu_00.objects.raw()的地方,看看你的SQL语句是不是没写cu_code。比如之前如果是这么写的:
# 错误写法:少了主键cu_code raw_query = "SELECT cu_nm FROM cu_00 WHERE cu_nm LIKE %s" results = Cu_00.objects.raw(raw_query, ['%' + keyword + '%'])
赶紧改成包含cu_code的版本:
# 正确写法:必须包含主键字段 raw_query = "SELECT cu_code, cu_nm FROM cu_00 WHERE cu_nm LIKE %s" results = Cu_00.objects.raw(raw_query, ['%' + keyword + '%'])
这样Django就能正常把结果转成Cu_00的实例,不会再报错了。
如果你根本不需要模型实例?换个查询方式
要是你只是想拿数据,不需要生成Django模型对象,那完全可以不用raw(),直接用数据库游标执行原生SQL,这种方式不要求必须包含主键:
from django.db import connection def cust_popup_view(request): if request.method == 'POST': # 处理POST参数 keyword = request.POST.get('keyword', '') with connection.cursor() as cursor: # 直接写你需要的字段就行 cursor.execute("SELECT cu_nm FROM cu_00 WHERE cu_nm LIKE %s", ['%' + keyword + '%']) # 获取结果,比如转成列表 results = [row[0] for row in cursor.fetchall()] # 后续处理逻辑 return ...
额外检查点:确认字段名匹配
虽然你的模型里已经把cu_code设为主键,但要确保数据库里的字段名和你SQL里写的一致——Django默认会把模型字段名转成小写存到数据库,所以除非你手动指定了db_column,否则用cu_code就没问题。
基本上这几种方法就能解决这个问题啦。
内容的提问来源于stack exchange,提问作者Jongpyo Jeon
相关产品推荐
相关产品推荐

