Python中存储库模式的实现?

2024-05-11 13:15:00 发布

您现在位置:Python中文网/ 问答频道 /正文

主要出于好奇,我正在寻找一个Python框架或示例,用于将持久性逻辑与域逻辑分离的存储库模式。

“Repository Pattern”这个名字出现在post“Untangle Domain and Persistence Logic with Curator”(Ruby)中,idea来自“领域驱动设计”一书中的sectionMartin Fowler。模型类不包含持久性逻辑,而是应用程序声明其实例类似于模型实例的内存集合的存储库子类。每个存储库以不同的方式保存模型,例如SQL(各种模式约定)、Riak或其他noSQL和内存(用于缓存)。框架约定意味着存储库子类通常需要最少的代码:只要声明SQLRepository的“Widget repository”子类,就会提供一个集合,将模型小部件持久化到名为“widgets”的DB表,并将列与小部件属性相匹配。

与其他模式的区别:

活动记录模式:例如,Django ORM。应用程序只定义具有域逻辑和一些持久性元数据的模型类。ORM将持久性逻辑添加到模型类中。这将域和持久性混合在一个类中(根据文章,这是不可取的)。

感谢@marcin,我发现当Active Record支持不同的后端和.save(使用=“other_database”)函数时,这就给了存储库模式的多后端好处。

所以在某种意义上,存储库模式就像活动记录一样,持久性逻辑被移动到一个单独的类中。

数据映射器模式:例如,SQLAlchemy的经典映射。应用程序为数据库表和从模型到表的数据映射器定义了其他类。因此,可以通过多种方式将模型实例映射到表,例如支持遗留模式。不要认为SQLAlchemy提供了到非SQL存储的映射程序。


Tags: 数据实例内存模型框架应用程序声明sql
2条回答

在我的脑海里:

我定义了两个示例域,UserAnimal,一个基本存储类Store,以及两个专门的存储类UserStoreAnimalStore。使用context manager关闭数据库连接(为简单起见,我在本例中使用sqlite):

import sqlite3

def get_connection():
    return sqlite3.connect('test.sqlite')

class StoreException(Exception):
    def __init__(self, message, *errors):
        Exception.__init__(self, message)
        self.errors = errors


# domains

class User():
    def __init__(self, name):
        self.name = name


class Animal():
    def __init__(self, name):
        self.name = name


# base store class
class Store():
    def __init__(self):
        try:
            self.conn = get_connection()
        except Exception as e:
            raise StoreException(*e.args, **e.kwargs)
        self._complete = False

    def __enter__(self):
        return self

    def __exit__(self, type_, value, traceback):
        # can test for type and handle different situations
        self.close()

    def complete(self):
        self._complete = True

    def close(self):
        if self.conn:
            try:
                if self._complete:
                    self.conn.commit()
                else:
                    self.conn.rollback()
            except Exception as e:
                raise StoreException(*e.args)
            finally:
                try:
                    self.conn.close()
                except Exception as e:
                    raise StoreException(*e.args)


# store for User obects
class UserStore(Store):

    def add_user(self, user):
        try:
            c = self.conn.cursor()
            # this needs an appropriate table
            c.execute('INSERT INTO user (name) VALUES(?)', (user.name,))
        except Exception as e:
            raise StoreException('error storing user')


# store for Animal obects
class AnimalStore(Store):

    def add_animal(self, animal):
        try:
            c = self.conn.cursor()
            # this needs an appropriate table
            c.execute('INSERT INTO animal (name) VALUES(?)', (animal.name,))
        except Exception as e:
            raise StoreException('error storing animal')

# do something
try:
    with UserStore() as user_store:
        user_store.add_user(User('John'))
        user_store.complete()

    with AnimalStore() as animal_store:
        animal_store.add_animal(Animal('Dog'))
        animal_store.add_animal(Animal('Pig'))
        animal_store.add_animal(Animal('Cat'))
        animal_store.add_animal(Animal('Wolf'))
        animal_store.complete()
except StoreException as e:
    # exception handling here
    print(e)

你可能想好好看看詹姆斯丹尼斯DictShield project

“DictShield是一个数据库不可知的建模系统。它提供了一种轻松建模、验证和重塑数据的方法。所有这些都不需要任何特定的数据库。”

相关问题 更多 >