在 Peewee 中识别更新的模型
Identifying updated models in Peewee
让我们假设以下 Peewee 模型:
class TestModel(Model):
id = IntegerField(primary_key=True)
name = CharField()
text = TextField()
class Meta:
database = db
如果我们有一个包含此模型实例的填充数据库,并且 select 所有这些实例,我们将得到以下结果:
>>> old_models = [m for m in TestModel.select()]
>>> # old_models contains two TestModels stored in DB:
>>> # TestModel(id=1, name='red', text='hello')
>>> # TestModel(id=5, name='blue', text='world')
现在,我们从外部来源获得了我们转换为模型的数据列表:
>>> new_models = []
>>> new_models.append(TestModel(id=1, name='red', text='hello'))
>>> new_models.append(TestModel(id=5, name='red', text='NOT WORLD'))
>>> new_models.append(TestModel(id=10, name='green', text='hello world'))
获取新添加的模型(即不存在于数据库中)和已添加的模型很容易:
>>> added_models = [m for m in new_models if m not in old_models]
>>> # added_models with contain TestModel with ID 10
查找已更新的模型的最有效方法是什么?在我们的例子中,ID 为 5 的模型。用新检索的数据覆盖现有模型将不起作用,因为脏字段是接触的每个字段。即使我们覆盖一个不相等的值,我们也会失去比较两个值(新旧值)的能力。有什么想法吗?
我认为模型 API 没有任何方法可以做到这一点,但如果您愿意依赖 peewee 模型的实现细节,则有一种方法可以做到。而且它在规模上可能不会很快。
m.__dict__['_data']
中有一个表示模型数据的字典供您使用。
首先,通过 id:
获取 dict
of old_models
old_models_by_id = {m.get_id(): m for m in old_models}
然后,编写一个简单的函数来比较两个模型的数据
def compare_models(m1, m2):
"""Return True if two models have exactly the same data"""
return m1.__dict__['_data'] == m2.__dict__['_data']
最后,获取更新的模型:
updated_models = [m for m in updated_models
if m.get_id() in old_models_by_id
and not compare_models(m, old_models_by_id.get(m.get_id()))]
建立@thaavik 的回答-
在现代 peewee 中(我使用的是 3.13),字典名称已更改为 __data__
所以你需要使用 m1.__dict__['__data__']
您可以做的其他事情是使用 dict
的 .items()
方法和 ^ 运算符(异或)来获得两个项目集之间的差异
a = {"a": 1, "c": 1}
b= {"b": 1, "c":2}
print(a.items()^ b.items())
> {('c', 1), ('c', 2), ('a', 1), ('b', 1)}
让我们假设以下 Peewee 模型:
class TestModel(Model):
id = IntegerField(primary_key=True)
name = CharField()
text = TextField()
class Meta:
database = db
如果我们有一个包含此模型实例的填充数据库,并且 select 所有这些实例,我们将得到以下结果:
>>> old_models = [m for m in TestModel.select()]
>>> # old_models contains two TestModels stored in DB:
>>> # TestModel(id=1, name='red', text='hello')
>>> # TestModel(id=5, name='blue', text='world')
现在,我们从外部来源获得了我们转换为模型的数据列表:
>>> new_models = []
>>> new_models.append(TestModel(id=1, name='red', text='hello'))
>>> new_models.append(TestModel(id=5, name='red', text='NOT WORLD'))
>>> new_models.append(TestModel(id=10, name='green', text='hello world'))
获取新添加的模型(即不存在于数据库中)和已添加的模型很容易:
>>> added_models = [m for m in new_models if m not in old_models]
>>> # added_models with contain TestModel with ID 10
查找已更新的模型的最有效方法是什么?在我们的例子中,ID 为 5 的模型。用新检索的数据覆盖现有模型将不起作用,因为脏字段是接触的每个字段。即使我们覆盖一个不相等的值,我们也会失去比较两个值(新旧值)的能力。有什么想法吗?
我认为模型 API 没有任何方法可以做到这一点,但如果您愿意依赖 peewee 模型的实现细节,则有一种方法可以做到。而且它在规模上可能不会很快。
m.__dict__['_data']
中有一个表示模型数据的字典供您使用。
首先,通过 id:
获取dict
of old_models
old_models_by_id = {m.get_id(): m for m in old_models}
然后,编写一个简单的函数来比较两个模型的数据
def compare_models(m1, m2):
"""Return True if two models have exactly the same data"""
return m1.__dict__['_data'] == m2.__dict__['_data']
最后,获取更新的模型:
updated_models = [m for m in updated_models
if m.get_id() in old_models_by_id
and not compare_models(m, old_models_by_id.get(m.get_id()))]
建立@thaavik 的回答-
在现代 peewee 中(我使用的是 3.13),字典名称已更改为 __data__
所以你需要使用 m1.__dict__['__data__']
您可以做的其他事情是使用 dict
的 .items()
方法和 ^ 运算符(异或)来获得两个项目集之间的差异
a = {"a": 1, "c": 1}
b= {"b": 1, "c":2}
print(a.items()^ b.items())
> {('c', 1), ('c', 2), ('a', 1), ('b', 1)}