Dan*_*har 4 python sqlalchemy flask-sqlalchemy
我有模特儿json column.模型和数据示例:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://...'
db = SQLAlchemy()
db.init_app(app)
app.app_context().push()
class Example(db.Model):
id = db.Column(db.Integer(), nullable=False, primary_key=True, )
json_field = db.Column(db.JSON())
db.create_all()
db.session.add(Example(json_field={'id': None}))
db.session.add(Example(json_field={'id': 1}))
db.session.add(Example(json_field={'id': 50}))
db.session.add(Example(json_field={}))
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
现在我尝试找到以下记录id == 1:
query = db.session.query(Example).filter(Example.json_field['id'] == 1)
print(query.all())
Run Code Online (Sandbox Code Playgroud)
然后我收到了下一个错误:
sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)运算符不存在:json = integer LINE 3:WHERE(example.json_field - >'id')= 1
原因.查看生成的查询:
SELECT example.id AS example_id, example.json_field AS example_json_field
FROM example
WHERE (example.json_field -> %(json_field_1)s) = %(param_1)s
Run Code Online (Sandbox Code Playgroud)
但在我的情况下,正确的查询应该是这样的:
SELECT * FROM example WHERE CAST(json_field->>'id' AS INTEGER) = 1;
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
我尝试过使用强制转换,但没有成功:
print(
db.session.query(Example).filter(
cast(Example.json_field['id'], Integer) == 1
).all()
)
Run Code Online (Sandbox Code Playgroud)
错误:
sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)无法将类型json转换为整数LINE 3:WHERE CAST((example.json_field - >'id')AS INTEGER)= 1
你可以看到where clause仍然是错的.此外,我需要使用范围(>,<=等等)的条件.感谢帮助.
Flask-SQLAlchemy的SQLAlchemy对象 - 通常命名db- 允许从sqlalchemy和访问函数等sqlalchemy.orm,因此db.JSON是不提供Postgresql特定运算符的泛型JSON类型.您应该使用sqlalchemy.dialects.postgresql.JSON:
from sqlalchemy.dialects.postgresql import JSON
class Example(db.Model):
id = db.Column(db.Integer(), nullable=False, primary_key=True, )
json_field = db.Column(JSON)
Run Code Online (Sandbox Code Playgroud)
使用适当的类型,您必须先将JSON显式转换为文本,然后转换为整数:
db.session.query(Example).\
filter(Example.json_field['id'].astext.cast(Integer) == 1)
Run Code Online (Sandbox Code Playgroud)
这产生了所需的谓词
CAST(json_field->>'id' AS INTEGER) = 1
Run Code Online (Sandbox Code Playgroud)
这同样适用于无法直接投射的所有类型json.SQLAlchemy的用于提供的组合的快捷方式astext和cast(),但它已在1.1及以上的版本被删除:
在1.1版中更改:对象
ColumnElement.cast()上的运算符JSON现在要求JSON.Comparator.astext显式调用修饰符,如果转换仅使用文本字符串.
您还可以在过滤器中使用原始 sql
from sqlalchemy import text
db.session.query(Example).filter(text("CAST(json_field->>'id' AS INTEGER) = 1")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4062 次 |
| 最近记录: |