繁体   English   中英

使用Pony ORM或sqlalchemy时,在哪里创建数据库对象?

[英]When using Pony ORM or sqlalchemy, where to create Database object?

我开始与对象关系映射器(特别是Pony ORM )一起玩。

Pony中 ,所有实体定义都继承自db.Entity类。 但是,为了做到这一点,当然需要首先在某个地方创建db对象。 db.Entity有点类似于在SQLAlchemy中声明的基础,所以我相信我下面的问题也是同样有效的SQLAlchemy)

我在Pony ORM文档中看到的所有示例都是内联的示例,其中在声明实体之前,只需在解释器提示中声明Database对象db

这给我留下了一个问题: 我应该在“真实”项目中的什么地方创建数据库对象?

尤其要考虑以下情况:我要将我的实体定义与实际使用这些实体的地方分开(例如,我只想构建一个不错的ORM包装程序包来访问数据库,然后在多个其他项目中使用它)。 然后,我可能希望用户提供自己的db对象,该对象根据他们的需要进行配置以便访问数据库。

一些示例代码:

假设我有一个存储人员地址的数据库,我的包my_orm应该为该数据库提供一个ORM,然后将在app.py使用app.py

my_orm / init .py

from my_orm.person import Person
from my_orm.address import Address

my_orm / person.py:

from pony.orm import Required

class Person(db.Entity): # Where should `db` be defined?
    name = Required(str)
    age = Required(int)

my_orm / address.py:

from pony.orm import Required

class Address(db.Entity): # Where should `db` be defined?. Must be the same `db` object as in person.py
    street_name = Required(str)
    zip_code = Required(int)

app.py

from pony.orm import Database
db = Database()
import my_orm

除了已经看起来很丑陋,因为它混合了导入和db的创建,还会引发错误NameError: name 'db' is not defined 那我该怎么办呢?

有几种组织代码的方法。

1.将所有实体放在一个文件中

这是用于中小型项目的便捷方式。 这是最简单的方法,也许您可​​以以此方式开始。 您可以在实体定义之前在此文件中定义Database对象:

models.py

from pony.orm import Database, Required, Optional

db = orm.Database()

class Person(db.Entity):
    name = Required(str)
    addresses = Set('Address') # or Set(lambda: Address)

class Address(db.Entity):
    street_name = Required(str)
    persons = Set('Person')

main.py

from models import db, Person, Address
from settings import db_params
from pony.orm import db_session, select

db.bind(**db_params)
db.generate_mapping(create_tables=True)

with db_session:
    persons = select(p for p in Person if p.age > 20)[:]

这种方法很简单,适合中型项目,您可以从它开始

2.在函数内部定义实体

如果要在同一程序中连接到Database多个不同实例,这可能很有用。

models.py

from pony.orm import Required, Optional

def define_entities(db):
    class Person(db.Entity):
        name = Required(str)
        addresses = Set('Address')

    class Address(db.Entity):
        street_name = Required(str)
        persons = Set('Person')

main.py

from models import define_entities
from settings import db_params
from pony.orm import Database, db_session, select

db = Database()
define_entities(db)
db.bind(**db_params)
db.generate_mapping(create_tables=True)

with db_session:
    persons = select(p for p in db.Person if p.age > 20)[:]

注意,可以将实体类作为数据库对象的属性来访问: db.Person 这可能很方便,因为不必导入Person实体-足以访问db对象。 缺点是,像PyCharm这样的IDE无法理解db.Person是什么,并且无法为诸如Person.name这样的属性提供代码完成建议。

也可以在从不同文件导入的多个函数之间拆分entiti定义:

models1.py

from pony.orm import Required, Optional

def define_entities(db):
    class Person(db.Entity):
        name = Required(str)
        addresses = Set('Address') # or: Set(lambda: db.Address)

models2.py

from pony.orm import Required, Optional

def define_entities(db):
    class Address(db.Entity):
        street_name = Required(str)
        persons = Set('Person')  # or: Set(lambda: db.Person)

main.py

import models1, models2
from settings import db_params
from pony.orm import Database, db_session, select

db = Database()
models1.define_entities(db)
models2.define_entities(db)
db.bind(**db_params)
db.generate_mapping(create_tables=True)

with db_session:
    persons = select(p for p in db.Person if p.age > 20)[:]

这可能是矫kill过正,但是当在应用程序启动后动态定义确切的实体集时,有时可以将其用于可插拔体系结构。

3.在单独的文件中定义实体(不在函数内部)

您可以遵循我在相应答案中描述的架构: PonyORM-多个模型文件

您可以使用元类来定义实体。

文件1:

class LazyEntityMeta(type):
    def __new__(mcs, name, bases, attrs):
        entity = mcs._entities[name] = LazyEntity(bases, attrs)
        return entity

    @classmethod
    def attach(mcs, db):
        for name, lazy in mcs._entities.items():
            lazy.entity = type(name, lazy.bases + (db.Entity,), attrs)

    _entities = {}

class LazyEntity:
    def __init__(self, bases, attrs):
        self.bases = bases
        self.attrs = attrs

文件2:

class A(metaclass=LazyEntityMeta):
    id = PrimaryKey(int, auto=True)

文件3:

db = Database()

LazyEntityMeta.attach(db)
db.bind('sqlite', ':memory:')
db.generate_mapping(create_tables=True)

with db_session:
    a1 = db.A()
    a2 = A.entity()

暂无
暂无

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

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