Django model 字段名称(db_column)含有单个%时,查询表格出现IndexError: tuple index out of range错误

在field中使用%表示百分数

软件版本

Django 2.2.16
Python 3.5.6 (基于Anaconda)

代码

models.py

# hello.models
from django.db import models

# Create your models here.
class UncorrectColumn(models.Model):
    # layoutset = models.ForeignKey(LayoutSet, on_delete=models.CASCADE)
    wake_loss = models.FloatField(db_column="尾流损失(%)", verbose_name="尾流损失(%)", default=1)

views.py

# hello.views
from django.shortcuts import render
from django.http import HttpResponse

from .models import  UncorrectColumn
# Create your views here.
def detail(request):
    q = UncorrectColumn.objects.all()
    print(q)
    UncorrectColumn.objects.create(wake_loss=0.1)

    return HttpResponse("Hello world!")

urls.py

from django.contrib import admin
from django.urls import path
from hello.views import detail

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', detail)
]

错误信息

使用postgresql数据库

File "D:\Anaconda\envs\py35\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "D:\Anaconda\envs\py35\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
IndexError: tuple index out of range

使用sqlite3数据库

  File "D:\Anaconda\envs\py35\lib\site-packages\django\db\backends\sqlite3\operations.py", line 155, in last_executed_query
    return sql % params
ValueError: unsupported format character ')' (0x29) at index 44

原因分析

Django在生成sql语句时直接复制了%,生成了如下语句:

'INSERT INTO "hello_uncorrectcolumn" ("尾流损失(%)") VALUES (%s) RETURNING "hello_uncorrectcolumn"."id"'

上述语句中VALUES(%s)由wake_loss实际值改写,但由于"尾流损失(%)"中的%,导致赋值出错。
在这里插入图片描述

解决方案

比较粗糙的解决方法,是修改${Python}\Lib\site-packages\django\db\models\sql\compiler.py中的代码,将field中的%%%代替,防止字符串被field的值错误替换。

    def as_sql(self):
        # We don't need quote_name_unless_alias() here, since these are all
        # going to be column names (so we can avoid the extra overhead).
        qn = self.connection.ops.quote_name
        opts = self.query.get_meta()
        insert_statement = self.connection.ops.insert_statement(ignore_conflicts=self.query.ignore_conflicts)
        result = ['%s %s' % (insert_statement, qn(opts.db_table))]
        fields = self.query.fields or [opts.pk]
        # result.append('(%s)' % ', '.join(qn(f.column) for f in fields))
        result.append('(%s)' % ', '.join(qn(f.column.replace('%', '%%')) for f in fields))
        # 

此外为了使print(q)不出错,还应修改get_select函数:

        for col, alias in select:
            try:
                sql, params = self.compile(col, select_format=True)
                
                #### 增加 #####
                sql = sql.replace('%', '%%')
                #####################
                
            except EmptyResultSet:
                # Select a predicate that's always False.
                sql, params = '0', ()
            ret.append((col, (sql, params), alias))
        return ret, klass_info, annotations
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值