如何正确使用应用引擎 Python 模型类的自定义 __init__? [英] How to use a custom __init__ of an app engine Python model class properly?

查看:16
本文介绍了如何正确使用应用引擎 Python 模型类的自定义 __init__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施延迟博客帖子删除方案.因此,您有 2 分钟的时间来取消删除,而不是烦人的你确定吗?.

I'm trying to implement a delayed blog post deletion scheme. So instead of an annoying Are you sure?, you get a 2 minute time frame to cancel deletion.

我想跟踪使用 db.Model 类 (DeleteQueueItem) 时将删除的内容,因为我发现无法从队列中删除任务,并且怀疑我可以查询那里的内容.

I want to track What will be deleted When with a db.Model class (DeleteQueueItem), as I found no way to delete a task from the queue and suspect I can query what's there.

创建一个 DeleteQueueItem 实体应该自动设置一个 delete_when 属性并将一个任务添加到队列中.我使用博客文章的相对路径作为他们的 key_name 并且想在这里使用它作为 key_name.这导致我使用自定义 init:

Creating a DeleteQueueItem entity should automatically set a delete_when property and add a task to the queue. I use the relative path of blog posts as their key_name and want to use that as key_name here, too. This led me to a custom init:

class DeleteQueueItem(db.Model):
    """Model to keep track of items that will be deleted via task queue."""

    # URL path to the blog post is handled as key_name
    delete_when = db.DateTimeProperty()

    def __init__(self, **kwargs):
        delay = 120  # Seconds
        t = datetime.timedelta(seconds=delay)
        deadline = datetime.datetime.now() - t
        key_name = kwargs.get('key_name')

        db.Model.__init__(self, **kwargs)
        self.delete_when = deadline

        taskqueue.add(url='/admin/task/delete_page', 
                      countdown=delay,
                      params={'path': key_name})

这似乎有效,直到我尝试删除实体:

This seems to work, until I try to delete the entity:

fetched_item = models.DeleteQueueItem.get_by_key_name(path)

这失败了:

TypeError: __init__() takes exactly 1 non-keyword argument (2 given)

我做错了什么?

推荐答案

通常,您不应该尝试覆盖 Model 类的 init 方法.虽然有可能正确,但正确的构造函数行为相当复杂,甚至可能会在不同版本之间发生变化,从而破坏您的代码(尽管我们尽量避免这样做!).部分原因是您自己的代码必须使用构造函数来构建新模型,还必须由框架使用构造函数来重新构建从数据存储区加载的模型.

Generally, you shouldn't try and override the init method of Model classes. While it's possible to get right, the correct constructor behaviour is fairly complex, and may even change between releases, breaking your code (though we try to avoid doing so!). Part of the reason for this is that the constructor has to be used both by your own code, to construct new models, and by the framework, to reconstitute models loaded from the datastore.

更好的方法是使用工厂方法,您可以调用该方法而不是构造函数.

A better approach is to use a factory method, which you call instead of the constructor.

此外,您可能希望在编写实体的同时添加任务,而不是在创建时添加.如果不这样做,最终会出现竞争条件:任务可能会在您将新实体存储到数据存储区之前执行!

Also, you probably want to add the task at the same time as you write the entity, rather than at creation time. If you don't, you end up with a race condition: the task may execute before you've stored the new entity to the datastore!

这是一个重构建议:

class DeleteQueueItem(db.Model):
    """Model to keep track of items that will be deleted via task queue."""

    # URL path to the blog post is handled as key_name
    delete_when = db.DateTimeProperty()

    @classmethod
    def new(cls, key_name):
        delay = 120  # Seconds
        t = datetime.timedelta(seconds=delay)
        deadline = datetime.datetime.now() - t

        return cls(key_name=key_name, delete_when=deadline)

    def put(self, **kwargs):
      def _tx():
        taskqueue.add(url='/admin/task/delete_page', 
                      countdown=delay,
                      params={'path': key_name},
                      transactional=True)
        return super(DeleteQueueItem, self).put(**kwargs)
      if not self.is_saved():
        return db.run_in_transaction(_tx)
      else:
        return super(DeleteQueueItem, self).put(**kwargs)

这篇关于如何正确使用应用引擎 Python 模型类的自定义 __init__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆