關於sqlalchemy中鍵值以雙下劃線開頭導致Unknown column錯誤的問題
在開發中遇到了一個奇葩的問題,設計的資料庫其中有Column以雙下劃線開頭,導致在執行中出現錯誤。
現在以例子來複現並解決錯誤。
首先建立資料表
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
__name VARCHAR(16),
age INT
);
該表為包含主鍵id,和另外兩個column(__name、age)的student資料表,其中一個column的鍵值以雙下劃線開頭。
mysql> DESC student; +--------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | __name | varchar(16) | YES | | NULL | | | age | int(11) | YES | | NULL | | +--------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
現在我們向其中插入兩條資料後檢視資料表
mysql> SELECT * FROM student;
+----+--------+------+
| id | __name | age |
+----+--------+------+
| 1 | zhang3 | 12 |
| 2 | wang2 | 10 |
+----+--------+------+
2 rows in set (0.00 sec)
這個時候我們就可以建立sql.py檔案通過sqlalchemy連線我們的資料庫
from sqlalchemy import Column, String, Integer, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 建立物件的基類:
Base = declarative_base()
# 定義User物件:
class Student(Base):
# 表的名字:
__tablename__ = 'student'
# 表的結構:
id = Column(Integer, primary_key=True, autoincrement=True)
__name = Column(String(20))
age = Column(Integer)
# 初始化資料庫連線:
engine = create_engine('mysql+mysqlconnector://root: [email protected]:3306/test')
# 建立DBSession型別:
DBSession = sessionmaker(bind=engine)
# 建立session物件並查詢
session = DBSession()
students = session.query(Student).filter().all()
print(students)
執行之後我們會發現出錯了
Traceback (most recent call last): File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 1193, in _execute_context context) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\default.py", line 507, in do_execute cursor.execute(statement, parameters) File "C:\Python\Python36\lib\site-packages\mysql\connector\cursor.py", line 566, in execute self._handle_result(self._connection.cmd_query(stmt)) File "C:\Python\Python36\lib\site-packages\mysql\connector\connection.py", line 530, in cmd_query result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query)) File "C:\Python\Python36\lib\site-packages\mysql\connector\connection.py", line 432, in _handle_result raise errors.get_exception(packet) mysql.connector.errors.ProgrammingError: 1054 (42S22): Unknown column 'student._Student__name' in 'field list' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:/Users/A/Desktop/db.py", line 25, in <module> students = session.query(Student).filter().all() File "C:\Python\Python36\lib\site-packages\sqlalchemy\orm\query.py", line 2737, in all return list(self) File "C:\Python\Python36\lib\site-packages\sqlalchemy\orm\query.py", line 2889, in __iter__ return self._execute_and_instances(context) File "C:\Python\Python36\lib\site-packages\sqlalchemy\orm\query.py", line 2912, in _execute_and_instances result = conn.execute(querycontext.statement, self._params) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 948, in execute return meth(self, multiparams, params) File "C:\Python\Python36\lib\site-packages\sqlalchemy\sql\elements.py", line 269, in _execute_on_connection return connection._execute_clauseelement(self, multiparams, params) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 1060, in _execute_clauseelement compiled_sql, distilled_params File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 1200, in _execute_context context) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 1413, in _handle_dbapi_exception exc_info File "C:\Python\Python36\lib\site-packages\sqlalchemy\util\compat.py", line 203, in raise_from_cause reraise(type(exception), exception, tb=exc_tb, cause=cause) File "C:\Python\Python36\lib\site-packages\sqlalchemy\util\compat.py", line 186, in reraise raise value.with_traceback(tb) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\base.py", line 1193, in _execute_context context) File "C:\Python\Python36\lib\site-packages\sqlalchemy\engine\default.py", line 507, in do_execute cursor.execute(statement, parameters) File "C:\Python\Python36\lib\site-packages\mysql\connector\cursor.py", line 566, in execute self._handle_result(self._connection.cmd_query(stmt)) File "C:\Python\Python36\lib\site-packages\mysql\connector\connection.py", line 530, in cmd_query result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query)) File "C:\Python\Python36\lib\site-packages\mysql\connector\connection.py", line 432, in _handle_result raise errors.get_exception(packet) sqlalchemy.exc.ProgrammingError: (mysql.connector.errors.ProgrammingError) 1054 (42S22): Unknown column 'student._Student__name' in 'field list' [SQL: 'SELECT student.id AS student_id, student.`_Student__name` AS `student__Student__name`, student.age AS student_age \nFROM student'] (Background on this error at: http://sqlalche.me/e/f405)
檢查錯誤,將會發現Unknown column 'student._Student__name'
明明定義的column是student.__name,為什變成了student._Student__name?
這就要從python的類說起了,python的類並沒有關於私有變數的定義,但是有個近似私有變數的處理。
這裡節選一段
>> Any identifier of the form__spam
(at least two leading underscores, at most one trailing underscore)is textually replaced with _classname__spam
, where classname
is thecurrent class name with leading underscore(s) stripped
是說類的定義中任何以雙下劃線開頭的變數都將被重新命名為 _類名__變數名 的形式
所以回到sqlalchemy的問題,就會發現student.__name被重新命名為了student._Student__name,而資料表中並沒有_Student__name,導致查詢出錯。
在不能夠改變資料庫的前提下如何修復這個錯誤呢?其實很簡單,只要將變數放在類定義外面就好了。
重新修改一下sql.py
from sqlalchemy import Column, String, Integer, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 建立物件的基類:
Base = declarative_base()
# 定義User物件:
class Student(Base):
# 表的名字:
__tablename__ = 'student'
# 表的結構:
id = Column(Integer, primary_key=True, autoincrement=True)
# 修該此處,將帶有雙下劃線的變數放在類外
Student.__name = Column(String(20))
Student.age = Column(Integer)
# 初始化資料庫連線:
engine = create_engine('mysql+mysqlconnector://root:[email protected]:3306/test')
# 建立DBSession型別:
DBSession = sessionmaker(bind=engine)
# 建立session物件並查詢
session = DBSession()
students = session.query(Student).filter().all()
for student in students:
print(student.__name)
此時再次執行程式碼
zhang3
wang2
結果正常!相關推薦
關於sqlalchemy中鍵值以雙下劃線開頭導致Unknown column錯誤的問題
在開發中遇到了一個奇葩的問題,設計的資料庫其中有Column以雙下劃線開頭,導致在執行中出現錯誤。現在以例子來複現並解決錯誤。首先建立資料表CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, __
類中以雙下劃線開始的方法
tin data .py docs track new 屬性 enc attr *參考:https://docs.python.org/2/reference/datamodel.html#special-method-names 一 經常使用: (1)__init
python中那些雙下劃線開頭得函式和變數
Python 用下劃線作為變數字首和字尾指定特殊變數 _xxx 不能用’from module import *’匯入 __xxx__ 系統定義名字 __xxx 類中的私有變數名 核心風格:避免用下劃線作為變數名的開始。 因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避
python類中的雙下劃線方法
att 他還 ret sel col 只有一個 war span instance __getitem__,__setitem__和__delitem__ 實現了對象屬性的字典化操作。 class Person: def __init__(self, na
python(七) Python中單下劃線和雙下劃線
www www. 自己 pro improt 分類 鏈接 默認 question Python中單下劃線和雙下劃線: 一、分類 (1)、以單下劃線開頭,表示這是一個保護成員,只有類對象和子類對象自己能訪問到這些變量。 以單下劃線開
Python中被雙下劃線包圍的魔法方法
按位異或 blog with pow ring 指定元素 運算 -c 描述 基本的魔法方法 __new__(cls[, ...]) 用來創建對象 1. __new__ 是在一個對象實例化的時候所調用的第一個方法 2. 它的第一個參數是這個類,其他的參數
67 orm13查詢語句,外鍵查詢,多對多查詢 單表查詢雙下劃線方法
ever tle 基礎 lte ron -s 執行流程 first 什麽 主要內容:https://www.cnblogs.com/maple-shaw/articles/9403501.html 註意: 如果想要文件中運行整個django項目: 需要在文件中寫入:
Python中單下劃線和雙下劃線有啥區別
__func__:一種約定,Python內部的名字,用來區別其他使用者自定義的命名,以防衝突。 _func: 一種約定,用來指定私有變數或私有函式(private) __func: 如果類中有一個方法與另外一個類中的一個方法同名了
Python類中的單下劃線和雙下劃線的區別
#"單下劃線" 開始的成員變數叫做保護變數,意思是隻有類物件和子類物件自己能訪問到這些變數; #"雙下劃線" 開始的是私有成員,意思是隻有類物件自己能訪問,連子類物件也不能訪問到 #-*-coding:utf8-*- class father(): def __init
Python中單、雙下劃線的區別總結
前言 Python 的程式碼風格由 PEP 8 描述。這個文件描述了 Python 程式設計風格的方方面面。在遵守這個文件的條件下,不同程式設計師編寫的 Python 程式碼可以保持最大程度的相似風格。這樣就易於閱讀,易於在程式設計師之間交流。 我們大家在學習Python的時候,好像
django 外來鍵查詢 一對多 通過物件查詢和通過filter values 雙下劃線查詢
表結構: from django.db import models class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField() pub_d
欄位和欄位的引數,查詢的13個方法,但標的雙下劃線外來鍵和多對多操作
欄位 常用欄位 AutoField() 自增列,必須填入引數 primary_key=True則成為資料庫的主鍵。無該欄位時,django自動建立 一個model不能有兩個AutoField欄位。 IntegerField() 一個整數
Python中帶下劃線或者雙下劃線的屬性使用。
以單下劃線開頭,表示這是一個保護成員,只有類物件和子類物件自己能訪問到這些變數。以單下劃線開頭的變數和函式被預設是內部函式,使用from module import *時不會被獲取,但是使用import module可以獲取。 以單下劃線結尾僅僅是為了區別該名稱與關鍵詞 雙下劃線開頭,表示為私有成員,只允
探究ConcurrentHashMap中鍵值對在Segment[]的下標如何確定
1 public ConcurrentHashMap(int initialCapacity, 2 float loadFactor, int concurrencyLevel) { 3 if (!(loadFactor
GridView中存在多行資料,如何獲取資料表主鍵值以對某一整行資料進行編輯
<%-- asp.net初學者,還請大神多多提點--%> 程式碼如下: protected void grvMHN_RowEditing(object sender, GridViewE
理解Python的雙下劃線命名(轉)
函數 python的函數 del 標準 開頭 變量名 cnblogs 通過 全局 add by zhj:今天在學習SimpleHTTPServer的源代碼時,看到了Python標準庫SocketServer模塊中有個BaseServer類,該類的__init__方法定義如下
python-day71--django多表雙下劃線查詢及分組聚合
cts 劃線 django del 就是 auth 分組聚合 with 沒有 #====================================雙下劃線的跨表查詢===============# 前提 此時 related_name=bookList 屬性
面對對象之私有屬性,以及單、雙下劃線 | Pythoon
指定 src 防止 什麽 mage 對象 class .com img # 在很多程序中會遇到__name,_name的標識符,在類中,如果屬性帶有雙 # 下劃線,表示私有屬性,通俗的講,就是不能在類命名空間外被直接調用,但是 # 可以通過方法來調用。 #
python 單下劃線和雙下劃線
base print 定義 gpo pass erl spa ble ... 1 underline.py 2 __all__ = [‘_underline_variable‘, ‘__underline_variable‘, ‘_underline_func‘,
理解Python的雙下劃線命名
public bject () 有變 weakref _weak 令行 方法 全部 引子 我熱情地邀請大家猜測下面這段程序的輸出: class A(object): def __init__(self): self.__priva