代码之家  ›  专栏  ›  技术社区  ›  Wieger

SQLalchemyprimaryjoin属性在Python 3.4中不工作(使用Python2.7工作)

  •  0
  • Wieger  · 技术社区  · 9 年前

    我最近尝试将代码从Python2.7升级到Python3.4。

    在Python 2.7中,这很简单:

    class Maatje(CommonColumns):
        koppelvoorstellen = db.relationship("Koppelvoorstel",
                            primaryjoin="or_(Maatje.id == Koppelvoorstel.deelnemerID," \
                            + "Maatje.id == Koppelvoorstel.vrijwilligerID)",
                            cascade="all,delete-orphan")
    

    但是,使用Python 3.4(和mod_wsgi 4.4,从源代码编译而来,与Python3.4相反),当我试图查询Maatje时,在我的Apache 2.4错误日志中出现了一个错误:

    [wsgi:error] [pid 6169] sqlalchemy.exc.ProgrammingError:      
    (mysql.connector.errors.ProgrammingError) 1064 (42000): You have an     
    error in your SQL syntax; check the manual that corresponds to your 
    MySQL server version for the right syntax to use near '%(param_1)s = 
    koppelvoorstel.`vrijwilligerID`' at line 3 [SQL: 'SELECT 
    koppelvoorstel.id AS koppelvoorstel_id, koppelvoorstel.aangemaakt AS     
    koppelvoorstel_aangemaakt, koppelvoorstel.gewijzigd AS 
    koppelvoorstel_gewijzigd, koppelvoorstel.etag AS koppelvoorstel_etag, 
    koppelvoorstel.`deelnemerID` AS `koppelvoorstel_deelnemerID`,    
    koppelvoorstel.`vrijwilligerID` AS `koppelvoorstel_vrijwilligerID`, 
    koppelvoorstel.akkoordvrijwilliger AS 
    koppelvoorstel_akkoordvrijwilliger, koppelvoorstel.akkoorddeelnemer AS 
    koppelvoorstel_akkoorddeelnemer, 
    koppelvoorstel.redenafwijzingvrijwilliger AS 
    koppelvoorstel_redenafwijzingvrijwilliger, 
    koppelvoorstel.redenafwijzingdeelnemer AS 
    koppelvoorstel_redenafwijzingdeelnemer, koppelvoorstel.stopdatum AS 
    koppelvoorstel_stopdatum, koppelvoorstel.redenstoppenvrijwilliger AS 
    koppelvoorstel_redenstoppenvrijwilliger, 
    koppelvoorstel.redenstoppendeelnemer AS 
    koppelvoorstel_redenstoppendeelnemer \\nFROM koppelvoorstel \\nWHERE %
    (param_1)s = koppelvoorstel.`deelnemerID` OR %(param_1)s = 
    koppelvoorstel.`vrijwilligerID`'] [parameters: {'param_1': 1}]
    

    在我看来,SQL是完全有效的(我假设\\n将成为一个换行符)。我使用phpMyAdmin(不带)尝试了SQL查询,并填充了参数(一个),它理解了查询并得出了有效的结果。

    我试过写 primaryjoin 在其他形式中,例如不带字符串、带or和带“|”作为或运算符。还尝试了 in_ -操作员。

    我使用Ubuntu 14.04和mod_wsgi 4.4、SQLalchemy 1.0.12和Flask SQLalchemi 2.1。

    我正在使用 python3-mysql.connector (用于MySQL Connector/Python的Ubuntu包)。

    如果我删除了其中一个等式比较(不管是哪一个),并且没有使用 or_ -运算符,则它不会抛出错误。但我需要同时使用 或_ -操作员。

    2016年3月6日: 现在我把问题隔离了一点。使用python2.7运行以下代码不会产生任何问题:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_ECHO'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://username:password@127.0.0.1/primaryjoindb'
    db = SQLAlchemy(app)
    
    class Coupleproposal(db.Model):
        __tablename__ = 'coupleproposal'
        id = db.Column(db.Integer, primary_key=True)
        participantID = db.Column(db.Integer, db.ForeignKey('buddy.id'), nullable = False)
        volunteerID = db.Column(db.Integer, db.ForeignKey('buddy.id'), nullable = False)
    
        participant = db.relationship("Buddy", foreign_keys=[participantID])
        volunteer = db.relationship("Buddy", foreign_keys=[volunteerID])
        __table_args__ = (db.UniqueConstraint('participantID', 'volunteerID', name='_couple_uc'),)
    
    class Buddy(db.Model):
        __tablename__ = 'buddy'
        id = db.Column(db.Integer, primary_key=True)
        coupleproposals = db.relationship("Coupleproposal", \
                        primaryjoin="(Buddy.id == Coupleproposal.participantID) | (Buddy.id == Coupleproposal.volunteerID)", \
                        cascade="all,delete-orphan")
    
    db.create_all()
    b1 = Buddy()
    b2 = Buddy()
    db.session.add(b1)
    db.session.add(b2)
    cp1 = Coupleproposal(participantID=1, volunteerID=1)
    db.session.add(cp1)
    db.session.commit()
    for aBuddy in db.session.query(Buddy).all():
        print(aBuddy.id)
        print(aBuddy.coupleproposals)
    

    但是使用python3.4运行代码会引发以下错误:

    sqlalchemy.exc.ProgrammingError:(mysql.connector.errors.Programming错误)1064(42000):您的SQL语法有错误;请查看与MySQL服务器版本对应的手册,了解在“%(param_1)s=coupleproposition”附近使用的正确语法。 volunteerID '在第3行[SQL:'选择coupupproposal.id作为coupuproposal_id,coupuproposal。 participantID 作为 coupleproposal_participantID ,情侣提议。 志愿者ID 作为 coupleproposal_volunteerID \nFROM coupleproposition\n其中%(param_1)s=coupleroposition。 参与者ID OR%(param_1)s=耦合方案。 志愿者ID '][参数:{'param_1':1}]

    1 回复  |  直到 9 年前
        1
  •  0
  •   Wieger    9 年前

    如果我使用不同的连接器(如pymysql),它会起作用。在这里回答(不是我,而是SQLalchemy的回购所有者): https://bitbucket.org/zzzeek/sqlalchemy/issues/3669/primaryjoin-attribute-with-or_-operator