SQLAlchemy進行混合屬性查詢時報錯:TypeError: Python method cannot be converted to a MySQL type

問題描述

使用 SQLAlchemy 的混合屬性進行查詢時報錯: TypeError: Python 'method' cannot be converted to a MySQL type




user.sql
在這裏插入圖片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `user` VALUES ('1', 'a');
INSERT INTO `user` VALUES ('2', 'b');
INSERT INTO `user` VALUES ('3', 'c');
SET FOREIGN_KEY_CHECKS = 1;

password.sql
在這裏插入圖片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `password`;
CREATE TABLE `password`  (
  `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `password` VALUES ('84a516841ba77a5b4648de2cd0dfcb30ea46dbb4', 'abc123');
INSERT INTO `password` VALUES ('86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', '123456');
INSERT INTO `password` VALUES ('e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98', 'abcdef');
SET FOREIGN_KEY_CHECKS = 1;

password.iduser.name hash後的結果



test.py

import hashlib
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(String(20), primary_key=True)
    name = Column(String(20))

    @hybrid_property
    def hash(self):
        # return '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'
        return hashlib.sha1(bytes(self.name, encoding='utf-8')).hexdigest()

    @hybrid_method
    def hash(self):
        return hashlib.sha1(bytes(self.name, encoding='utf-8')).hexdigest()  # 該方法一定得可轉爲SQL的方法


class Password(Base):
    __tablename__ = 'password'  # 表名
    id = Column(String(20), primary_key=True)
    password = Column(String(20))

    def __repr__(self):
        return '{} {}'.format(self.id, self.password)


engine = create_engine('mysql+mysqlconnector://root:123456@localhost:3306/test')  # 用戶名root,口令123456
DBSession = sessionmaker(bind=engine)
session = DBSession()

# 這樣不行
print(session.query(Password).join(User, Password.id == User.hash).filter(User.id == '1').one())

# 這樣也不行
# stmt = session.query(User).filter(User.id == '1').subquery()
# print(session.query(Password).filter(Password.id == stmt.hash).one())

session.close()




解決方案

SQLAlchemy對混合屬性進行Python操作,其Python操作必須在SQL中,否則會報該錯誤

因此本人覺得只能分開查詢,因爲hash操作是Python層面的東西,很難轉換到SQL

import hashlib
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(String(20), primary_key=True)
    name = Column(String(20))

    @hybrid_property
    def hash(self):
        # return '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'
        return hashlib.sha1(bytes(self.name, encoding='utf-8')).hexdigest()


class Password(Base):
    __tablename__ = 'password'  # 表名
    id = Column(String(20), primary_key=True)
    password = Column(String(20))

    def __repr__(self):
        return '{} {}'.format(self.id, self.password)


engine = create_engine('mysql+mysqlconnector://root:123456@localhost:3306/test')  # 用戶名root,口令123456
DBSession = sessionmaker(bind=engine)
session = DBSession()

# 這樣不行
# print(session.query(Password).join(User, Password.id == User.hash).filter(User.id == '1').one())

# 這樣也不行
# stmt = session.query(User).filter(User.id == '1').subquery()
# print(session.query(Password).filter(Password.id == stmt.hash).one())

# 分開查詢
user = session.query(User).filter(User.id == '1').one()
hash = user.hash
password = session.query(Password).filter(Password.id == hash).one()
print(password)

session.close()




參考文獻

  1. SQLAlchemy:如何擴展混合屬性?
  2. 混合屬性 — SQLAlchemy Documentation
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章