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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章