1. 程式人生 > >關於sqlalchemy中鍵值以雙下劃線開頭導致Unknown column錯誤的問題

關於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