У меня есть база данных mysql, в которой есть две таблицы, которые я хочу использовать в тестах - Shop и Discrict. Прежде всего, вот список desc
:
root@localhost [flowershop]> describe catalog_shop;
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| hours | varchar(255) | NO | | NULL | |
| lat | varchar(255) | NO | | NULL | |
| lng | varchar(255) | NO | | NULL | |
| phone | varchar(255) | NO | | NULL | |
| address | varchar(255) | NO | | NULL | |
| calltracking_id | int(11) | YES | | NULL | |
| district_id | int(11) | NO | MUL | NULL | |
| modification_date | datetime(6) | NO | | NULL | |
| show_on_site | tinyint(1) | NO | | NULL | |
| sms_phone | varchar(255) | NO | | NULL | |
| user_id | int(11) | YES | UNI | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
12 rows in set (0.07 sec)
root@localhost [flowershop]> describe catalog_district;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| article_id | int(11) | YES | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
В моих models.py:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import relationship
from sqlalchemy import Column, ForeignKey
from tornado_sqlalchemy import make_session_factory
from .settings import DATABASE_URL
session_factory = make_session_factory(DATABASE_URL)
AutoBase = automap_base()
AutoBase.prepare(session_factory.engine, reflect=True)
Shop = AutoBase.classes.catalog_shop
District = AutoBase.classes.catalog_district
tests / factories.py:
import factory
from packages.models import Shop, District, session_factory
session = session_factory.make_session()
class DistrictFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = District
sqlalchemy_session = session
sqlalchemy_session_persistence = 'commit'
class ShopFactory(factory.alchemy.SQLAlchemyModelFactory):
district = factory.SubFactory(DistrictFactory)
address = factory.Faker('address')
phone = factory.Faker('phone_number')
class Meta:
model = Shop
sqlalchemy_session = session
sqlalchemy_session_persistence = 'commit'
test_handlers.py:
from tornado.testing import AsyncTestCase
from .factories import ShopFactory
class StartHandlerTest(AsyncTestCase):
def test_simple_start(self):
shop = ShopFactory.create()
Который при вызове дает мне обратную трассировку:
ERROR: test_simple_start (packages.tests.test_handlers.StartHandlerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/tornado/testing.py", line 98, in __call__
result = self.orig_method(*args, **kwargs)
File "/Users/alkalit/.virtualenvs/flowershop/telegram_bot/packages/tests/test_handlers.py", line 13, in test_simple_start
shop = ShopFactory.create()
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 564, in create
return cls._generate(enums.CREATE_STRATEGY, kwargs)
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 501, in _generate
return step.build()
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/builder.py", line 279, in build
kwargs=kwargs,
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 315, in instantiate
return self.factory._create(model, *args, **kwargs)
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/alchemy.py", line 75, in _create
obj = model_class(*args, **kwargs)
File "<string>", line 4, in __init__
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 441, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
raise value
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 438, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/ext/declarative/base.py", line 840, in _declarative_constructor
"%r is an invalid keyword argument for %s" % (k, cls_.__name__)
TypeError: 'district' is an invalid keyword argument for catalog_shop
Я также ссылался на себя с документами sqlalchemy, которые утверждают, что при создании автоматической модели он также обеспечивает отношения: https://docs.sqlalchemy.org/en/13/orm/extensions/automap.html#basic-use
а именно: session.add(Address(email_address="foo@bar.com", user=User(name="foo")))
Итак, вопрос в том - что я делаю не так?
Я также пытался использовать "родной" создатель сессий в factories.py
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine
engine = create_engine(DATABASE_URL)
session = scoped_session(sessionmaker(bind=engine))
с тем же результатом.
libs:
- tornado == 6.0.3
- tornado-sqlalchemy == 0.6.1
- SQLAlchemy == 1.3.10
- factory-boy == 2.12.0
Редактировать: добавлено sqlalchemy_session_persistence = 'commit'
, но все равно появляется ошибка.