簡體   English   中英

如何正確使用app引擎Python模型類的自定義__init__?

[英]How to use a custom __init__ of an app engine Python model class properly?

我正在嘗試實施延遲博客帖子刪除方案。 所以不是討厭你確定嗎? ,你得到2分鍾的時間框架來取消刪除。

我想跟蹤什么將被刪除當使用db.Model類( DeleteQueueItem )時,我發現無法從隊列中刪除任務並懷疑我可以查詢那里有什么。

創建DeleteQueueItem實體應該自動設置delete_when屬性並將任務添加到隊列中。 我使用博客文章的相對路徑作為其key_name,並希望在此處將其用作key_name 這導致我進入自定義初始化

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

這似乎有效,直到我嘗試刪除實體:

fetched_item = models.DeleteQueueItem.get_by_key_name(path)

這失敗了:

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

我究竟做錯了什么?

通常,您不應嘗試覆蓋Model類的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()

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM