Use MongoEngine's abstract Document class to define common fields, so that duplicated code are reduced

When using MongoEngine in my python app, I often have to write duplicated field definition code in many Document classes. This article show a way to avoid it.

Code before optimization

import mongoengine as me
import datetime


class User(me.Document):
    name = me.StringField()
    created_time = me.DateTimeField(default=datetime.datetime.now)


class Post(me.Document):
    title = me.StringField()
    created_time = me.DateTimeField(default=datetime.datetime.now)

As we can see above, both User and Post have the created_time field, so we got duplicated code created_time = me.DateTimeField(default=datetime.datetime.now).

Abstract Document class

We can create an abstract class by setting the abstract attribute of meta. Here's an example:

import mongoengine as me

class BaseDoc(me.Document):
    # common fields here
    meta = {
        'abstract': True,
    }

This abstract class can be the base class of other Document classes so that they can share common fields.

Share common fields of the abstract class

In the code below, we show a practical example:

import mongoengine as me
import datetime

# abstract Document class
class BaseDoc(me.Document):
    created_time = me.DateTimeField(default=datetime.datetime.now)
    meta = {
        'abstract': True
    }

# normal Document class
class User(BaseDoc):
    name = me.StringField()


# another normal Document class
class Post(BaseDoc):
    title = me.StringField()


me.connect('test')

user = User(name="jack").save()
print(user.created_time)

post = Post(title='hello').save()
print(post.created_time)

User and Post inherited the BaseDoc class, so that they can share the common field created_time.

Posted on 2023-02-27