- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 Python 项目中使用干净的架构和 TDD 开发方法。从 SQLAlchemy 1.3 更新到 SQLAlchemy 1.4 后,无法针对内存中的 Postgres 数据库进行测试,我找不到解决该问题的方法。
遵循 DDD 原则,该项目使用新的命令式映射语法,替换经典映射声明。
这是一个最小的(非)工作示例,改编自 SQLAlchemy 文档: https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#orm-imperative-mapping
它需要在本地安装和运行 PostgreSQL。
from sqlalchemy import MetaData, Table, Column, Integer, String
from sqlalchemy.orm import registry
from myapp import model
mapper_registry = registry()
metadata = MetaData()
user_table = Table(
'tb_user',
mapper_registry.metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('nickname', String(12))
)
mapper_registry.map_imperatively(model.User, user_table)
from dataclasses import dataclass
from dataclasses import field
@dataclass
class User:
id: int = field(init=False)
name: str = ""
fullname: str = ""
nickname: str = ""
import tempfile
import pytest
from pytest_postgresql import factories
from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.orm import clear_mappers
from sqlalchemy.orm import configure_mappers
from myapp import model
from myapp.orm import mapper_registry
from sqlalchemy.orm import sessionmaker
# here, we set up postgresql in-memory:
socket_dir = tempfile.TemporaryDirectory()
postgresql_my_proc = factories.postgresql_proc(
port=None,
unixsocketdir=socket_dir.name,
)
postgresql_my = factories.postgresql("postgresql_my_proc")
@pytest.fixture
def in_memory_db(postgresql_my):
def db_creator():
return postgresql_my.cursor().connection
engine = create_engine("postgresql+psycopg2://", creator=db_creator)
mapper_registry.metadata.create_all(bind=engine)
return engine
@pytest.fixture
def session(in_memory_db):
clear_mappers()
configure_mappers()
Session = sessionmaker(bind=in_memory_db)
session = Session()
yield session
clear_mappers()
def test_User_mapper_can_add(session):
user = model.User(fullname="John Smith")
session.add(user)
session.commit()
rows = list(session.execute("SELECT fullname FROM tb_user"))
assert rows == [("John Smith",)]
===== test session starts =====
platform linux -- Python 3.9.4, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /home/lionel/code/sqla14_test
plugins: postgresql-3.1.1
collected 1 item
tests/test_postgresql_inmemory.py F [100%]
==== FAILURES =====
___ test_User_mapper_can_add ___
self = <sqlalchemy.orm.session.Session object at 0x7fe876060c70>
instance = <[AttributeError("'User' object has no attribute 'id'") raised in repr()] User object at 0x7fe875f487c0>
_warn = True
def add(self, instance, _warn=True):
"""Place an object in the ``Session``.
Its state will be persisted to the database on the next flush
operation.
Repeated calls to ``add()`` will be ignored. The opposite of ``add()``
is ``expunge()``.
"""
if _warn and self._warn_on_events:
self._flush_warning("Session.add()")
try:
> state = attributes.instance_state(instance)
E AttributeError: 'User' object has no attribute '_sa_instance_state'
../../myvenv/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2554: AttributeError
The above exception was the direct cause of the following exception:
session = <sqlalchemy.orm.session.Session object at 0x7fe876060c70>
def test_User_mapper_can_add(session):
user = model.User(fullname="John Smith")
> session.add(user)
tests/test_postgresql_inmemory.py:53:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../.cache/pypoetry/virtualenvs/sqla14-5BJjO56U-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2556: in add
util.raise_(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def raise_(
exception, with_traceback=None, replace_context=None, from_=False
):
r"""implement "raise" with cause support.
:param exception: exception to raise
:param with_traceback: will call exception.with_traceback()
:param replace_context: an as-yet-unsupported feature. This is
an exception object which we are "replacing", e.g., it's our
"cause" but we don't want it printed. Basically just what
``__suppress_context__`` does but we don't want to suppress
the enclosing context, if any. So for now we make it the
cause.
:param from\_: the cause. this actually sets the cause and doesn't
hope to hide it someday.
"""
if with_traceback is not None:
exception = exception.with_traceback(with_traceback)
if from_ is not False:
exception.__cause__ = from_
elif replace_context is not None:
# no good solution here, we would like to have the exception
# have only the context of replace_context.__context__ so that the
# intermediary exception does not change, but we can't figure
# that out.
exception.__cause__ = replace_context
try:
> raise exception
E sqlalchemy.orm.exc.UnmappedInstanceError: Class 'myapp.model.User' is not mapped
../../myvenv/lib/python3.9/site-packages/sqlalchemy/util/compat.py:207: UnmappedInstanceError
-------- Captured stderr setup ----
sh: warning: setlocale: LC_ALL: cannot change locale (C.UTF-8)
/bin/sh: warning: setlocale: LC_ALL: cannot change locale (C.UTF-8)
========short test summary info =====
FAILED tests/test_postgresql_inmemory.py::test_User_mapper_can_add - sqlalchemy.orm.exc.UnmappedInstanceError: Clas...
=========1 failed in 1.18s ==========
您是否看到需要更改哪些内容才能通过测试?
最佳答案
我可以通过包装 mapper_registry.map_imperatively(...)
使测试通过在 start_mappers
函数中,就像我之前做的那样。
我最初认为我必须用 configure_mappers
替换它 - SQLAlchemy documentation .
from sqlalchemy import MetaData, Table, Column, Integer, String
from sqlalchemy.orm import registry
from myapp import model
metadata = MetaData()
mapper_registry = registry(metadata=metadata)
user_table = Table(
'tb_user',
mapper_registry.metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('nickname', String(12))
)
def start_mappers():
mapper_registry.map_imperatively(model.User, user_table)
摘录:
from myapp.orm import start_mappers
# …
@pytest.fixture
def session(in_memory_db):
clear_mappers()
start_mappers()
Session = sessionmaker(bind=in_memory_db)
session = Session()
yield session
clear_mappers()
def test_User_mapper_can_add(session):
user = model.User(fullname="John Smith")
session.add(user)
session.commit()
rows = list(session.execute("SELECT fullname FROM tb_user"))
assert rows == [("John Smith", )]
[Sat Jun 5 19:42:46 2021] Running: py.test tests/test_postgresql_inmemory.py
===== test session starts ====
platform linux -- Python 3.9.4, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /home/lionel/code/myapp
plugins: postgresql-3.1.1
collected 1 item
tests/test_postgresql_inmemory.py . [100%]
===== 1 passed in 1.12s ====
关于python - 使用 SQLAlchemy 1.4 经典/命令式映射样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67852380/
我正在尝试创建一个使用 UUID 作为主键的用户模型: from src.db import db # SQLAlchemy instance import sqlalchemy_utils impo
在 sqlalchemy 中,我试图合并表,然后使用 WHERE 和 ORDER_BY 创建别名 有点像 SELECT * FROM ( SELECT [TABLE_ONE].[SOME_ID]
我正在使用 SQL Alchemy(通过 Flask_sqlalchemy)将 Python 字典列表插入到 Postgres 数据库中。 其中一个表是所有唯一项目的列表(表 1),而第二个是与某个项
This source详细说明如何使用关联代理创建具有 ORM 对象值的 View 和对象。 但是,当我附加一个与数据库中现有对象匹配的值(并且所述值是唯一的或主键)时,它会创建一个冲突的对象,因此我
SQLAlchemy Core和SQLAlchemy ORM的目的有什么区别? 最佳答案 顾名思义,ORM是一个对象关系映射器:其目的是将数据库关系表示为Python对象。 核心是查询构建器。其目的是
带有ForeignKey的Column是否自动创建索引? 还是我需要手动添加index=True? some_field = Column(Integer, ForeignKey(SomeModel.
我有一个主数据库,每个客户自己的数据库连接存储在其中。 因此,每个客户端都使用2个db:main和它自己的db,必须确定其连接 对于每个http调用。我如何使用flask-sqlalchemy扩展名执
当我仅对类进行继承时,它才起作用 class User(Base): __tablename__ = ’users’ id = Column(Integer, primary_key=
从用户的角度来看,SQLAlchemy 的查询日志似乎有点过于冗长,有时甚至有点神秘: 2015-10-02 13:51:39,500 INFO sqlalchemy.engine.base.Engi
我正在尝试使用 wtforms.ext.sqlalchemy QuerySelectMultipleField 显示复选框列表,但我无法在 GET 的表单上显示模型数据。 这是我的models.py
我想为查询返回一个中继连接。使用标准的 graphene-sqlalchemy 你可以这样做: class Query(graphene.ObjectType): node = relay.N
我在 centos 7.5 虚拟机上部署了最新的 Airflow ,并将 sql_alchemy_conn 和 result_backend 更新到 postgresql 实例上的 postgres
我想将多个项目插入到一个表中,并在发生冲突时更新该表。这是我想出的以下内容 from sqlalchemy.dialects.postgresql import insert meta = MetaD
我有以下模型: class Item(Base): a = relationship() b = relationship() c = relationship() d
我有 presto 和 superset 设置。 presto 运行良好,可以通过命令访问: ./app/hadoop/setjdk8.sh;bin/presto-cli --server http:
我一直在寻找一种在 sqlalchemy 中使用 tsvector 的方法(就像 INTEGER 等其他方法一样),但到目前为止我还不清楚如何做到这一点。我读过可以使用 UserDefinedType
我正在使用 sqlalchemy(现在使用 sqlite,但稍后可能会改变)来构建一个数据库,其中插入的顺序和 rowids 很重要。我基本上有以下几点: class Message(Base):
给定一个对象,我想知道如何知道它是否是 sqlalchemy 映射模型的实例。 通常,我会使用 isinstance(obj, DeclarativeBase)。但是,在这种情况下,我没有可用的 De
我已经通读了查询文档,如果有办法从查询中获取表名,就看不到任何地方 - 例如如果我有 q = query(Users) ,我可以得到Users从 q 退出? 最佳答案 请注意,像您这样的事件简单查询可
我不确定如何定义create schema foo迁移?我的模型如下所示(我正在使用Flask-Migrate): class MyTable(db.Model): __tablename__
我是一名优秀的程序员,十分优秀!