[英]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.