2011-11-11 28 views
22

Tôi đang cố thêm thuộc tính creation_time vào tài liệu của mình. Sau đây sẽ là một ví dụ:Thuộc tính Mongoengine creation_time trong Tài liệu

import datetime 

class MyModel(mongoengine.Document): 
    creation_date = mongo.DateTimeField() 
    modified_date = mongo.DateTimeField(default=datetime.datetime.now) 

mô hình Django đã xây dựng trong tham số cho DateTimeField đối tượng của họ như add_now, vv nhưng MongoEngine không hỗ trợ này.

Tôi tự hỏi nếu cách tốt nhất để làm điều này là như sau:

m,created = MyModel.objects.get_or_create() 
if created: 
    m.creation_date = datetime.datetime.now() 

hoặc nếu có một cách đẹp hơn tốt hơn.

Trả lời

48

Bạn có thể ghi đè phương thức lưu.

class MyModel(mongoengine.Document): 
    creation_date = mongo.DateTimeField() 
    modified_date = mongo.DateTimeField(default=datetime.datetime.now) 

    def save(self, *args, **kwargs): 
     if not self.creation_date: 
      self.creation_date = datetime.datetime.now() 
     self.modified_date = datetime.datetime.now() 
     return super(MyModel, self).save(*args, **kwargs) 
+0

Đây chính là những gì tôi cần. Tôi đã tìm ra bit mặc định, nhưng việc ghi đè phương thức lưu để theo dõi thời gian sửa đổi là hoàn hảo. Cảm ơn bạn :) – Dawson

+0

Vấn đề với điều này mặc dù là chức năng lưu sẽ không được gọi nếu bạn thực hiện cập nhật thay vì a.tiết kiệm phải không? – Nazariy1995

+0

@ Brenden1995 Không, nó không hoạt động với bản cập nhật. – Willian

-7

Bạn có thể sử dụng auto_now_add tham số theo documentation:

class MyModel(mongoengine.Document): 
    creation_date = mongo.DateTimeField(auto_now_add = True) 
    modified_date = mongo.DateTimeField(auto_now = True) 
+0

các tham số này không hoạt động trong mongoengine – josephmisiti

+1

Đó là điều không may nhất. Sau đó, ghi đè tiết kiệm như trong câu trả lời được chấp nhận là câu trả lời đúng. Tôi muốn tạo ra một bản vá để thêm các tính năng mặc dù :) –

+0

Đây không phải là Django dude ... –

0

Theo truyền thống, tôi đã thiết lập mặc định creation_date để datetime.now() và sau đó đã ẩn lĩnh vực này về hình thức quản trị, do đó bạn loại bỏ khả năng xảy ra người dùng ghi đè giá trị chính xác. Điều đó đòi hỏi hầu như không có mã.

Ghi đè phương thức lưu theo đề xuất của Willian cũng hiệu quả vì bạn có thể lập trình chặn bất kỳ cập nhật nào cho creation_date và cập nhật modfied_date cùng một lúc.

+1

khi bạn nói "theo truyền thống", ý bạn là sử dụng Django ORM hoặc MongoEngine cụ thể? – josephmisiti

18

Là một sang một bên, thời gian tạo được đóng dấu vào các thuộc tính _id - nếu bạn làm:

YourObject.id.generation_time 

sẽ cung cấp cho bạn một con tem datetime.

+0

Chính xác những gì tôi đang tìm kiếm, cảm ơn. –

+2

Điều này tốt hơn câu trả lời được chấp nhận. Tôi đã sử dụng '@ property' trên một hàm như thế này để có được created_time:' def created_at (self): return self.id.generation_time nếu self.id else None' – aaaronic

4
# -*- coding: utf-8 -*- 
from mongoengine import * 
from mongoengine import signals 
from datetime import datetime 

class User(Document): 
    email = StringField(required=True, unique=True) 
    first_name = StringField(max_length=50) 
    last_name = StringField(max_length=50) 
    # audit fields 
    created_on = DateTimeField(default=datetime.now()) 
    updated_on = DateTimeField(default=datetime.now()) 

    @classmethod 
    def pre_save(cls, sender, document, **kwargs): 
     document.updated_on = datetime.now() 

signals.pre_save.connect(User.pre_save, sender=User) 
4

Một giải pháp tốt đẹp đang sử dụng lại một trình xử lý tín hiệu đơn cho nhiều tài liệu.

class User(Document): 
    # other fields... 
    created_at = DateTimeField(required=True, default=datetime.utcnow) 
    updated_at = DateTimeField(required=True) 

class Post(Document): 
    # other fields... 
    created_at = DateTimeField(required=True, default=datetime.utcnow) 
    updated_at = DateTimeField(required=True) 

def update_timestamp(sender, document, **kwargs): 
    document.updated_at = datetime.utcnow() 

signals.pre_save.connect(update_timestamp, sender=User) 
signals.pre_save.connect(update_timestamp, sender=Post) 

Hãy cẩn thận để gán một callable và không cố định có giá trị như là mặc định, ví dụ default=datetime.utcnow mà không (). Một số câu trả lời khác trên trang này không chính xác và sẽ khiến cho created_at để tài liệu mới luôn được đặt vào thời điểm ứng dụng của bạn được tải lần đầu tiên.

Nó cũng luôn luôn tốt hơn để lưu trữ ngày UTC (datetime.utcnow thay vì datetime.now) trong cơ sở dữ liệu của bạn.

1

Nếu bạn đang sử dụng trường dấu thời gian trong một loạt tài liệu, bạn có thể giữ mã của mình DRY bằng cách tạo Tài liệu trừu tượng thay thế.

from datetime import datetime 
from mongoengine import Document 

class CreateUpdateDocument(Document): 
    meta = { 
     'abstract': True 
    } 

    # last updated timestamp 
    updated_at = DateTimeField(default=datetime.now) 

    # timestamp of when entry was created 
    created_at = DateTimeField(default=datetime.now) 

    def save(self, *args, **kwargs): 
     if not self.created_at: 
      self.created_at = datetime.now() 
     self.updated_at = datetime.now() 
     return super(CreateUpdateDocument, self).save(*args, **kwargs) 
+2

Bạn có thể muốn đặt 'self.updated_at = datetime .now() 'dưới một câu lệnh' else', vì vậy bạn có thể giữ ý tưởng "nếu update_at là none, điều đó có nghĩa là mô hình không bao giờ được cập nhật". – ldavid

3

giải pháp ưa thích của tôi là sử dụng @property trang trí để trả lại datetime tạo như chiết xuất từ ​​ObjectId:

@property 
def creation_stamp(self): 
    return self.id.generation_time 
Các vấn đề liên quan