Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timestamp Mixin for auto-populated created_at, updated_at #535

Open
roman-right opened this issue Apr 13, 2023 Discussed in #514 · 5 comments
Open

Timestamp Mixin for auto-populated created_at, updated_at #535

roman-right opened this issue Apr 13, 2023 Discussed in #514 · 5 comments
Assignees

Comments

@roman-right
Copy link
Member

Discussed in #514

Originally posted by slavovthinks March 25, 2023
Hey, folks 👋
Here is a Timestamp Mixin I've created for Beanie Documents. I'm wondering should I create a PR for it to be included as part of the project itself 🤔

from typing import Optional
from datetime import datetime

from pydantic import BaseModel, Field
from beanie import Document, before_event, Insert, Update, SaveChanges, Replace


class TimestampMixin(BaseModel):
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: Optional[datetime] = None

    @before_event(Insert)
    def set_created_at(self):
        self.created_at = datetime.utcnow()

    @before_event(Update, SaveChanges, Replace)
    def set_updated_at(self):
        self.updated_at = datetime.utcnow()
        
class ExampleDocument(TimestampMixin, Document):
    ...

```</div>
@humbertogontijo
Copy link

This stopped working recently

@Kinjalrk2k
Copy link

The created_at is working for me, but not the updated_at
After adding a few logs in the hook, I see that the value of updated_at is getting set correctly, however it's not being updated to the database!

@humbertogontijo
Copy link

I'm using this

from datetime import datetime
from typing import Any

from beanie import Document, Insert, Replace, SaveChanges, Update, WriteRules, before_event
from pydantic import Field
from pymongo.client_session import ClientSession


class BaseDocument(Document):
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    @before_event(Insert)
    def set_created_at(self) -> None:
        self.created_at = datetime.utcnow()

    @before_event(Update, SaveChanges, Replace)
    def set_updated_at(self) -> None:
        self.updated_at = datetime.utcnow()

    async def save(
        self,
        session: ClientSession | None = None,
        link_rule: WriteRules = WriteRules.DO_NOTHING,
        ignore_revision: bool = False,
        **kwargs: Any
    ) -> None:
        self.updated_at = datetime.utcnow()
        return await super().save(session, link_rule, ignore_revision, **kwargs)

Overriding the save was because before_event save wasnt reliable

@Kinjalrk2k
Copy link

Kinjalrk2k commented Feb 19, 2024

Instead of .save() I used .insert() and it seems to work that way!

Example:

new_user = User(...) # Like invoking the constructor of the model class
new_user.insert()
new_user.fetch_all_links() # (optional)

@francisdeh
Copy link

francisdeh commented Feb 22, 2024

I modified what @roman-right did, added Save event as well and doc.save() updates the date. Without that the date was not updated as indicated by @humbertogontijo. But i didnt have to ovverride the save method.

@before_event(Update, SaveChanges, Save, Replace)
 def set_updated_at(self):
     self.updated_at = naive_utcnow()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants