art049 / odmantic

Sync and Async ODM (Object Document Mapper) for MongoDB based on python type hints
http://art049.github.io/odmantic
ISC License
1.02k stars 95 forks source link

[Feature]: Add support for mixing models. #304

Open wiseaidev opened 1 year ago

wiseaidev commented 1 year ago

Feature request

Hey everyone. I recently came across this package and immediately fell in love; In fact, I am using it to build a pretty damn project. One thing I see is missing and worth adding is the ability to mix multiple models. This is especially useful for following the DRY principle. For instance, all models i want to create must contain two common columns, creation and updated records timestamps for monitoring purposes. Hence, the definition of a TimestampMixin model as follows:

from datetime import datetime
from odmantic import Field, Index, Model
from typing import Optional

class TimestampMixin(Model):
    """
    The TimestampMixin model
    Args:
        Model (odmantic.Model): Base odmontic model.
    """

    creation_date: Optional[datetime] = Field(default_factory=datetime.utcnow)
    modified_date: Optional[datetime]

And mix this model with the base model provided by ODMantic for all subsequent models:

class User(Model, TimestampMixin):
    """
    The User model
    Args:
        Model (odmantic.Model): Base odmontic model.
        TimestampMixin (odmantic.Model): Common Timestamp Mixin.
    """

    first_name: str = Field(index=True)
    last_name: str = Field(...)
    email: EmailStr = Field(index=True)
    password: str = Field(index=True)

Fortunately, odmantic didn't complain about this, but the columns are not created in the documents stored in MongoDB. This means that it is most likely not supported by the current release of odmantic.

Context

SQLAlchemy has a declarative_mixins decorator which allows you to define mixins for your models. So, it might be worth checking it out and adding support for something similar.

Additional Context

If possible, I would like to contribute towards adding support for this feature. Just need a little heads-up on the codebase and where this method should be implemented.

That's pretty much it. Have a nice day/evening.

agerwick commented 2 weeks ago

This seems like a very sensible feature to have. Are there any workarounds at the moment, beyond defining all common columns on all models?