简体   繁体   English

如何使用peewee的Use作为装饰器来动态指定数据库?

[英]how to use peewee's Using as a decorator to dynamically specify a database?

Despite numerous recipes and examples in peewee's documentation; 尽管peewee的文档中有许多食谱和例子; I have not been able to find how to accomplish the following: 我一直无法找到如何完成以下任务:

For finer-grained control, check out the Using context manager / decorator . 要获得更细粒度的控件,请查看Using context manager / decorator This allows you to specify the database to use with a given list of models for the duration of the wrapped block. 这允许您在包装块的持续时间内指定要与给定模型列表一起使用的数据库。

I assume it would go something like... 我认为它会像...

db = MySQLDatabase(None)


class BaseModelThing(Model):
    class Meta:
        database = db


class SubModelThing(BaseModelThing):
    '''imagine all the fields'''  
    class Meta:
        db_table = 'table_name'  

runtime_db = MySQLDatabase('database_name.db', fields={'''imagine field mappings here''', **extra_stuff)

@Using(runtime_db, [SubModelThing])
@runtime_db.execution_context()
def some_kind_of_query():
    '''imagine the queries here'''

but I have not found examples, so an example would be the answer to this question. 但我没有找到例子,所以一个例子就是这个问题的答案。

Yeah, there's not a great example of using Using or the execution_context decorators, so the first thing is: don't use the two together. 是的,没有使用Usingexecution_context装饰器的好例子,所以首先要做的是:不要将两者结合使用。 It doesn't appear to break anything, just seems to be redundant. 它似乎没有破坏任何东西,似乎是多余的。 Logically that makes sense as both of the decorators cause the specified model calls in the block to run in a single connection/transaction. 逻辑上这是有意义的,因为两个装饰器都会导致块中指定的模型调用在单个连接/事务中运行。

The only(/biggest) difference between the two is that Using allows you to specify the particular database that the connection will be using - useful for master/slave (though the Read slaves extension is probably a cleaner solution). 两者之间的唯一(/最大)不同的是, Using允许您指定的连接将使用特定数据库-主/从有用(虽然读奴隶扩展可能是一个清洁的解决方案)。

If you run with two databases and try using execution_context on the 'second' database (in your example, runtime_db ) nothing will happen with the data. 如果您使用两个数据库运行并尝试在“第二个”数据库上使用execution_context (在您的示例中为runtime_db ),则数据不会发生任何事情。 A connection will be opened at the start of the block and closed and the end, but no queries will be executed on it because the models are still using their original database. 连接将在块的开头打开并关闭和结束,但不会对其执行任何查询,因为模型仍在使用其原始数据库。

The code below is an example. 下面的代码就是一个例子。 Every run should result in only 1 row being added to each database. 每次运行都应该导致每个数据库只添加一行。

from peewee import *

db = SqliteDatabase('other_db')
db.connect()

runtime_db = SqliteDatabase('cmp_v0.db')
runtime_db.connect()


class BaseModelThing(Model):
    class Meta:
        database = db


class SubModelThing(Model):
    first_name = CharField()
    class Meta:
        db_table = 'table_name'

db.create_tables([SubModelThing], safe=True)
SubModelThing.delete().where(True).execute() # Cleaning out previous runs

with Using(runtime_db, [SubModelThing]):
    runtime_db.create_tables([SubModelThing], safe=True)
    SubModelThing.delete().where(True).execute()

@Using(runtime_db, [SubModelThing], with_transaction=True)
def execute_in_runtime(throw):
    SubModelThing(first_name='asdfasdfasdf').save()
    if throw: # to demo transaction handling in Using
        raise Exception()

# Create an instance in the 'normal' database
SubModelThing.create(first_name='name')

try: # Try to create but throw during the transaction
    execute_in_runtime(throw=True)
except:
    pass  # Failure is expected, no row should be added

execute_in_runtime(throw=False) # Create a row in the runtime_db

print 'db row count: {}'.format(len(SubModelThing.select()))

with Using(runtime_db, [SubModelThing]):
    print 'Runtime DB count: {}'.format(len(SubModelThing.select()))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM