tortoise-orm
tortoise-orm copied to clipboard
Usage with Tornado (was: No DB associated to model)
from tortoise.models import Model
from tortoise.fields import *
class Tournament(Model):
id = IntField(pk=True)
name = TextField()
if __name__ == "__main__":
from tortoise import Tortoise, run_async
async def init():
# Here we create a SQLite DB using file "db.sqlite3"
# also specify the app name of "models"
# which contain models from "app.models"
await Tortoise.init(
db_url='sqlite://otc.db',
modules={'models': ['model']} # 传入模块名称,本模块名为 model
)
# Generate the schema
await Tortoise.generate_schemas()
run_async(init())
async def dps():
await Tournament.create(name='Another Tournament')
# Now search for a record
tour = await Tournament.filter(name__contains='Another').first()
print(tour.name)
run_async(dps())
============================== tortoise.exceptions.ConfigurationError: No DB associated to model
WHY ?
Hi asyncins
run_async() is a helper function that ensures connections are closed when it is done:
https://tortoise-orm.readthedocs.io/en/latest/setup.html#cleaningup
https://tortoise-orm.readthedocs.io/en/latest/setup.html#tortoise.run_async
Only use it once:
from tortoise import Tortoise, run_async
from tortoise.models import Model
from tortoise.fields import *
class Tournament(Model):
id = IntField(pk=True)
name = TextField()
async def init():
# Here we create a SQLite DB using file "db.sqlite3"
# also specify the app name of "models"
# which contain models from "app.models"
await Tortoise.init(
db_url='sqlite://otc.db',
modules={'models': ['model']} # 传入模块名称,本模块名为 model
)
# Generate the schema
await Tortoise.generate_schemas()
async def dps():
await Tournament.create(name='Another Tournament')
# Now search for a record
tour = await Tournament.filter(name__contains='Another').first()
print(tour.name)
async def main():
await init()
await dps()
if __name__ == "__main__":
run_async(main())
Or, alternatively manage the loop & cleanup yourself.
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(Tortoise.close_connections())
Hi asyncins
run_async()is a helper function that ensures connections are closed when it is done: https://tortoise-orm.readthedocs.io/en/latest/setup.html#cleaningup https://tortoise-orm.readthedocs.io/en/latest/setup.html#tortoise.run_asyncOnly use it once:
from tortoise import Tortoise, run_async from tortoise.models import Model from tortoise.fields import * class Tournament(Model): id = IntField(pk=True) name = TextField() async def init(): # Here we create a SQLite DB using file "db.sqlite3" # also specify the app name of "models" # which contain models from "app.models" await Tortoise.init( db_url='sqlite://otc.db', modules={'models': ['model']} # 传入模块名称,本模块名为 model ) # Generate the schema await Tortoise.generate_schemas() async def dps(): await Tournament.create(name='Another Tournament') # Now search for a record tour = await Tournament.filter(name__contains='Another').first() print(tour.name) async def main(): await init() await dps() if __name__ == "__main__": run_async(main())Or, alternatively manage the loop & cleanup yourself.
loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.run_until_complete(Tortoise.close_connections())
========================== I used it in the tornado project. But,just do it your way, and the result is still wrong: ‘tortoise.exceptions.ConfigurationError: No DB associated to model’
Traceback (most recent call last): File "/home/asyncins/anaconda3/envs/envpoll/lib/python3.7/site-packages/tortoise/models.py", line 47, in db return current_transaction_map[self.default_connection].get() KeyError: None
Sorry, I didn't test my example, there was 2 issues.
In Tortoise.init(), the modules param, it tries to import a module called "models" which would work if you have a models.py in the path.
If you define the models in the same file, you should either use the name of the module, or '__main__'
When I take that example and do:
await Tortoise.init(
db_url='sqlite://otc.db',
modules={'models': ['__main__']} # Change here
)
# Generate the schema
It works for me
I don't have much experience with Tornado, at least not since they adopted asyncio event loop.
I imagine it will have a setup section, and in there you call await init(), and in the teardown section you should call await Tortoise.close_connections().
Then in the HTTP requests you should just use the ORM as per normal.
We should probably have a small tutorial or integration projects for the common frameworks. :thinking:
I don't have much experience with Tornado, at least not since they adopted
asyncioevent loop. I imagine it will have a setup section, and in there you callawait init(), and in the teardown section you should callawait Tortoise.close_connections(). Then in the HTTP requests you should just use the ORM as per normal.We should probably have a small tutorial or integration projects for the common frameworks. thinking
I like this ORM very much. It's very similar to Django ORM. It's very enjoyable to use.
I now have a lightweight Tornado project that wants to use the same lightweight Sqlite, but now it seems that they don't work well together, which is a great pity.
OK!
grigi, Thank you !
If need to use Tortoise in tornado, you need to specify sqliter files when starting tornado.
It works for me
from tornado.web import Application
from tornado import ioloop
from tornado.options import options, define
from tortoise import Tortoise
from urls import router
from component.home.model import AddVersionModel
# define 定义一些可以在命令行中传递的参数以及类型
define('port', default=8888, help='run on the given port', type=int)
define('debug', default=True, help='set tornado debug mode', type=bool)
options.parse_command_line()
if __name__ == "__main__":
async def run():
await Tortoise.init(db_url='sqlite://db.sqlite3',
modules={'models': ['__main__']})
await Tortoise.generate_schemas()
app = Application(router, debug=options.debug)
app.listen(port=options.port)
loops = ioloop.IOLoop.current()
loops.run_sync(run)
loops.start()
Chinese explanation:如果需要在Tornado中使用Tortoise,则需要在启动Tornado时指定sqliter文件。 照着示例代码启动就行,使用 ORM 跟平时无异。
Thank you! I will note to turn this into documentation.
Hello everyone! I get the same error in my aiohttp project.
Here is my db_init.py
from tortoise import Tortoise, run_async
from tight_trader.settings import config
DSN = "postgres://{user}:{password}@{host}:{port}/{database}"
async def create_tables(url):
await Tortoise.init(
db_url=url, modules={'models': ['tight_trader.trading_bot.models',
]}
)
await Tortoise.generate_schemas()
if __name__ == '__main__':
db_url = DSN.format(**config['postgres'])
run_async(create_tables(db_url))
models.py
import asyncio
from aiologger import Logger
from tortoise.models import Model
from tortoise import fields
from tight_trader.trading_bot.enums import BotType
logger = Logger.with_default_handlers(name=__name__)
class BaseTradingBot(Model):
""" Abstract trading bot model """
id = fields.IntField(pk=True)
name = fields.CharField(max_length=100)
type = None
on = fields.BooleanField(default=False)
frequency = fields.IntField(default=1)
instruments = None # to set up all instruments bot can trade
class Meta:
abstract = True
def __str__(self):
return 'Trading Bot {}'.format(self.id)
def _tear_down(self):
""" Makes all actions bot needs to stop trading"""
self.session.stop()
class CryptoBot(BaseTradingBot):
""" """
type = BotType.CRYPTO
I get the error when i try to
@aiohttp_jinja2.template('trading_bot/list.html')
def bot_list(request):
context = {'bots': CryptoBot.all()}
I didn't understand what is the right way to solve the problem. init script creates proper database tables. But seems that cant match them with the models
@SultanNasyrovDeveloper could you please show stacktrace for error and elaborate on how are you launching you script
Tortoise works (+ with migrations) in Tornado 6.0.3 and I have been using it for a while:
Define the models inside a folder called models under the root directory of the project. Just create an __init__.py file like this:
__models__ = [
SomeModel,
...
]
Then use tornado.options for your configurations:
{
'connections': {
'mysql': {
'engine': 'tortoise.backends.mysql',
'credentials': {
'host': options.mysql_host,
'port': options.mysql_port,
'user': options.mysql_user,
'password': options.mysql_password,
'database': options.mysql_database,
},
}
},
'apps': {
'models': {'models': ['models'], 'default_connection': 'mysql'}
},
}
For your tornado.web.Application, you can create your entry-point like this:
try:
IOLoop.current().run_sync(init) # Initialize your database here.
IOLoop.current().start() # Application starts here.
except KeyboardInterrupt:
_logger.warning('Keyboard interruption detected!')
finally:
IOLoop.current().stop()
_logger.warning('Closing the database connections!')
# Using Tornado's IOLoop throws this error for some reason:
# tornado.util.TimeoutError: Operation timed out after None seconds
# So, I use asyncio here.
get_event_loop().run_until_complete(Tortoise.close_connections())
You can then do the initialization procedures you want inside the init function:
await Tortoise.init(...)
if options.mysql_sync:
# Generate schemas
# Init table entries
# ...
Thanks for this, Will help in building an example/docs.
Hi there, I got the same error in sanic this is my Folder tree:
.
├── docs
│ └── test.md
├── src
│ ├── config.py
│ ├── __init__.py
│ ├── logs
│ │ └── blog.log
│ ├── models.py
│ ├── server.py
│ ├── tools
│ │ ├── __init__.py
│ │ ├── loggerFormatTools.py
│ │ ├── responseFormatTools.py
│ │ └── simpleTools.py
│ ├── urls.py
│ └── views
│ ├── blogViews.py
│ └── __init__.py
└── test
├── aaa.py
├── dbClientTest.py
├── functionTest.py
├── __init__.py
└── markdownTest.py
there are some model in src/models.py
class Blog(models.Model):
id = fields.IntField(pk=True)
aritcle_id = fields.CharField(max_length=20, unique=True)
titile = fields.CharField(max_length=128)
digest = fields.CharField(max_length=255)
cover = fields.CharField(max_length=255, null=True)
content = fields.TextField()
tags = fields.CharField(max_length=255)
browse = fields.IntField(default=0)
praise = fields.IntField(default=0)
c_time = fields.DatetimeField(auto_now_add=True)
u_time = fields.DatetimeField(auto_now=True)
is_delete = fields.BooleanField(default=False)
def __str__(self):
return f"<BlogObj article_id={self.aritcle_id}>"
class Meta:
table = 'blogs'
index = ["tags", "id_delete"]
ordering = ["-c_time", "-u_time"]
and my config file like this:
TORTOISE_CONFIG = {
"db_url": "mysql://admin:[email protected]:3306/Test?maxsize=32&minsize=8&echo=True",
"modules": {
'models': ['models'],
}
}
I tried got blogs in blogView.py, but It raise error
No DB associated to model
I have tried to create a models folder, and then move models.py into and create the __init__.py file.
And I change the TORTOISE_CONFIG after that:
TORTOISE_CONFIG = {
"db_url": "mysql://admin:[email protected]:3306/Test?maxsize=32&minsize=8&echo=True",
"modules": {
'models': ['__main__'],
}
}
It raise another error :
RuntimeWarning: Module "__main__" has no models
cls._init_apps(apps_config)
what should I do ?
Run await Tortoise.init() on app startup.
@long2ice Hi, Dear, I think I found the problem
在配置文件中引用models 的路径, 应该是相对于你注册tortoise的相对路径,
The path that refers to models' in the configuration file should be relative to the path where you register tortoise.
比如, 在我的问题中, 我的文件树是这个样子的:
For example, in my question, my file tree looks like this:
.
├── docs
│ └── test.md
├── src
│ ├── config.py
│ ├── __init__.py
│ ├── logs
│ │ └── blog.log
│ ├── models.py
│ ├── server.py
│ ├── tools
│ │ ├── __init__.py
│ │ ├── loggerFormatTools.py
│ │ ├── responseFormatTools.py
│ │ └── simpleTools.py
│ ├── urls.py
│ └── views
│ ├── blogViews.py
│ └── __init__.py
└── test
├── aaa.py
├── dbClientTest.py
├── functionTest.py
├── __init__.py
└── markdownTest.py
我的 src/server.py 文件是这样的:
My src/server.py is like this:
from sanic import Sanic
from src.config import PROJECT_CONFIG, LOGGING_CONFIG, SERVER_CONFIG
from src.urls import server_bp
from tortoise.contrib.sanic import register_tortoise
server = Sanic('abcdefg', log_config=LOGGING_CONFIG)
server.config.update(PROJECT_CONFIG)
server.blueprint(server_bp)
register_tortoise(server, **server.config.TORTOISE_CONFIG)
if __name__ == '__main__':
print(server.config.BASE_DIR)
server.run(**SERVER_CONFIG)
我的配置文件是这样的:
and this is my config file
TORTOISE_CONFIG = {
"db_url": "mysql://admin:[email protected]:3306/Blog?maxsize=32&minsize=8&echo=True",
"modules": {
'models': ['models'],
}
}
如果我在配置文件中想要使用 __main__ 参数来引入所有模型, 那么我的配置文件应该这样修改:
If I want to introduce all models with the __main__ parameter in my config file, my config file should be modified as follows:
TORTOISE_CONFIG = {
"db_url": "mysql://admin:[email protected]:3306/Blog?maxsize=32&minsize=8&echo=True",
"modules": {
'models': ['__main__'], # 这里做了修改(here is changed)
}
}
然后我应该手动的在tortoise的注册页面引用所有的模型, 所以我的server.py应该这样修改
after that, I should import all models in the registration page of tortoise, so my server.py follows:
from sanic import Sanic
from src.config import PROJECT_CONFIG, LOGGING_CONFIG, SERVER_CONFIG
from src.urls import server_bp
from tortoise.contrib.sanic import register_tortoise
from models import * # 引入所有的模型(import all models)
server = Sanic('abcdefg', log_config=LOGGING_CONFIG)
server.config.update(PROJECT_CONFIG)
server.blueprint(server_bp)
register_tortoise(server, **server.config.TORTOISE_CONFIG)
if __name__ == '__main__':
print(server.config.BASE_DIR)
server.run(**SERVER_CONFIG)
如果我想使用 model 文件的路径来进行注册的话, 那我应该把配置文件中的models 改成 models.py 相对于 server.py的路径:
If I want to use the path of model' file for registration, I should change models' in the configuration file to the path of models.py relative to server.py:
TORTOISE_CONFIG = {
"db_url": "mysql://admin:[email protected]:3306/Blog?maxsize=32&minsize=8&echo=True",
"modules": {
'models': ['src.models'],# 这里做了修改(here is changed)
}
}
server.py不需要做任何的改动
the server.py needn't do any change
然后 tortoise-orm 就可以正常工作了, 我想其他的框架也应该如此, 如果你也遇到了这个问题, 可以参考修改一下引用模型的相对位置.
Then tortoise-orm can work normally, and I think other frameworks should do the same. If you got the same error, you can refer to and modify the relative position of the reference model.
Hope It's useful to everyone !
see here https://tortoise-orm.readthedocs.io/en/latest/examples/fastapi.html#