SQLAlchemy中的Where子句

时间:2017-06-21 08:30:48

标签: python flask sqlalchemy flask-sqlalchemy

我对SQLAlchemy有疑问。

目前我有两个使用Flask的模型 - SQLAlchemy:

class Action(db.Model):

    __tablename__ = 'ACTION'

    _FIELDS_LABELS = ("ID", "MODULE_ID", "CATEGORY", "LABEL", "COMMAND", "ARGS", "FILE_ID")
    _REPR_FIELDS = ("MODULE_NAME", "FILE_NAME")

    id = db.Column(_FIELDS_LABELS[0], db.Integer, primary_key=True)
    module_id = db.Column(_FIELDS_LABELS[1], db.Integer, db.ForeignKey('MODULE.ID'))
    category = db.Column(_FIELDS_LABELS[2], db.String())
    label = db.Column(_FIELDS_LABELS[3], db.String())
    command = db.Column(_FIELDS_LABELS[4], db.String())
    args = db.Column(_FIELDS_LABELS[5], db.String())
    file_id = db.Column(_FIELDS_LABELS[6], db.Integer(), db.ForeignKey('FILE.ID'))

    file = db.relationship('File')

class Module(db.Model):

    __tablename__ = 'MODULE'

    _FIELDS_LABELS = ("ID", "NAME")

    id = db.Column(_FIELDS_LABELS[0], db.Integer,  primary_key=True)
    name = db.Column(_FIELDS_LABELS[1], db.String(), unique=True)
    actions = db.relationship('Action')

使用Flask,我尝试使用URL进行操作:

http://ip:port/modules/0/actions/18

所以我有一个行动蓝图:

action_blueprint = Blueprint('action',
                             __name__,
                             url_prefix="/modules/<string:module_id>/actions")

路线:

@action_blueprint.route('/', methods=['GET'])
def read_all(module_id):

    if module_id == '*':
        if len(request.args) == 0:
            actions = Action.query.all()
            return jsonify(list_to_json(actions))
        else:
            try:
                action = Action.query.filter_by(**request.args.to_dict()).first()
                return jsonify(action.serialize)
            except InvalidRequestError as i:
                return json_response(400, "InvalidRequestError : {}".format(i.args))
    else:
        try:
            module = Module.query.get(module_id)
        except AttributeError as a:
            return json_response(400, "'{}' needed to be '*' or a number.".format(module_id))

        if len(request.args) == 0:
            return jsonify(actions=list_to_json(module.actions))

        action = Action.query.join(Module).filter(Module.id == module_id).filter_by(**request.args.to_dict()).first()
        return jsonify(action.serialize)

但我有以下错误:

AttributeError: 'NoneType' object has no attribute 'serialize'

生成的查询:

SELECT "ACTION"."ID" AS "ACTION_ID", "ACTION"."MODULE_ID" AS "ACTION_MODULE_ID", "ACTION"."CATEGORY" AS "ACTION_CATEGORY", "ACTION"."LABEL" AS "ACTION_LABEL", "ACTION"."COMMAND" AS "ACTION_COMMAND", "ACTION"."ARGS" AS "ACTION_ARGS", "ACTION"."FILE_ID" AS "ACTION_FILE_ID"
FROM "ACTION" JOIN "MODULE" ON "MODULE"."ID" = "ACTION"."MODULE_ID"
WHERE "MODULE"."ID" = ? AND "MODULE"."ID" = ?

查询结束时出现问题,但我不知道是否

action = Action.query.join(Module).filter(Module.id == module_id).filter_by(**request.args.to_dict()).first()

是否正确。

1 个答案:

答案 0 :(得分:1)

通过查看生成的查询,您的问题有些明显。

WHERE "MODULE"."ID" = ? AND "MODULE"."ID" = ?

应该表明存在某些不妥之处,除非两个值相同,在这种情况下谓词是多余的。很明显

request.args.to_dict()

生成一个像

这样的字典
{ 'id': <some value> }

由于Query.filter_by()的工作原理,这一点很清楚:

  

关键字表达式是从查询的主要实体或作为Query.join() 调用目标的最后一个实体中提取的。

因此,在您的情况下,它会提取Module的id属性并添加过滤条件Module.id == <some value>。修复程序取决于您的请求args的用途。

另外因为Query.first()可能会返回None,你应该以某种方式解释它。

action = Action.query...first()

if action:
    return jsonify(action.serialize)

else:
    # Handle not found