简体   繁体   English

在 Peewee 中识别更新的模型

[英]Identifying updated models in Peewee

Let's assume the following Peewee model:让我们假设以下 Peewee 模型:

class TestModel(Model):
    id = IntegerField(primary_key=True)
    name = CharField()
    text = TextField()

    class Meta:
        database = db

If we have a populated database with instances of this model, and select them all, we get the following results:如果我们有一个包含此模型实例的填充数据库,并将它们全部选中,我们将得到以下结果:

>>> 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')

Now, from an external source, we get a list of data that we convert into our models:现在,从外部来源,我们得到一个数据列表,我们将其转换为我们的模型:

>>> 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'))

Getting newly-added models (ie not present in the DB) and those that have been added is easy:获取新添加的模型(即不存在于数据库中)和已添加的模型很容易:

>>> added_models = [m for m in new_models if m not in old_models]
>>> # added_models with contain TestModel with ID 10

What's the most efficient way to find those models that have been updated though?找到那些已更新的模型的最有效方法是什么? In our case, the model with ID 5. Overwriting the existing models with the newly-retrieved data won't work because a dirty field is every field that is touched.在我们的例子中,ID 为 5 的模型。用新检索的数据覆盖现有模型将不起作用,因为脏字段是每个被触及的字段。 And even if we overwrite a value if it does not equal, then we lose the ability to compare both values (new and old).即使我们覆盖一个不相等的值,我们也会失去比较两个值(新旧)的能力。 Any ideas?有什么想法吗?

I don't think there's any way to do this with the Model API, but there is a way to do it if you are willing to depend on an implementation detail of peewee Models.我认为 Model API 没有任何方法可以做到这一点,但是如果您愿意依赖于 peewee 模型的实现细节,那么有一种方法可以做到这一点。 Also it probably won't be very fast at scale.此外,它的规模可能不会很快。

There is a dict representing the Model's data in m.__dict__['_data'] that you can use.m.__dict__['_data']中有一个表示模型数据的m.__dict__['_data'] ,您可以使用。

First, get a dict of old_models by id:首先,通过 id 获取old_modelsdict

old_models_by_id = {m.get_id(): m for m in old_models}

Then, write a simple function comparing two Model's data然后,编写一个简单的函数比较两个模型的数据

def compare_models(m1, m2):
    """Return True if two models have exactly the same data"""
    return m1.__dict__['_data'] == m2.__dict__['_data']

Finally, get updated models:最后,获取更新的模型:

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()))]

building upun @thaavik's answer- in modern peewee (im using 3.13) the dict name was changed to __data__ so you need to use m1.__dict__['__data__']构建 upun @thaavik 的答案-在现代 peewee(我使用 3.13)中,dict 名称已更改为__data__因此您需要使用m1.__dict__['__data__']

somthing else you can do is use dict 's .items() method and the ^ operator (Exclusive Or) to get the difference between the two item sets您可以做的其他事情是使用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)}

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

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