在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