Why exclude() in MongoEngine does not exclude all fields?

Viewed 2025

As MongoEngine says in documentation:

only(*fields) Load only a subset of this document’s fields.

post = BlogPost.objects(...).only('title', 'author.name')

Now I run the same on my own user collection as below:

user = User.objects(__raw__=condition).only('status').get()

But when I print the output (print user.to_json()) it gives a result like below:

{"_id": {"$oid": "59ba3c7428999b08223dc4aa"}, "cover": "", "avatar": "", "dob": {"$date": 1505347200000}, "created_at": {"$date": 1505384574064}, "updated_at": {"$date": 1505384574064}, "bio": "", "location": "", "account_type": "regular", "status": "inactive", "phone": ""}

I don't think I have missed something here.

Now I use exclude to blacklist some fields:

user = User.objects(__raw__=condition).exclude('status').exclude('username').exclude('bio').exclude('email').get()

Output is:

{"_id": {"$oid": "59ba3c7428999b08223dc4aa"}, "fullname": "Mu Fullname", "password": "$pbkdf2-sha256$16366$y9lbq/Ueo5QSohSi1FrLmQ$YOLu.KzmLiDhS6BVh4cTPg7xFpYLZ/2l478jnROj0ok", "cover": "", "avatar": "", "dob": {"$date": 1505347200000}, "created_at": {"$date": 1505377384359}, "updated_at": {"$date": 1505377384359}, "bio": "", "location": "", "verification": {"email": false, "celebrity": false, "phone": false}, "account_type": "regular", "status": "inactive", "phone": ""}

username and email is excluded, but not status and bio.

My User model is:

class Verification(EmbeddedDocument):
    email = BooleanField(default=False, allow_blank=True, allow_null=True)
    celebrity = BooleanField(default=False, allow_blank=True, allow_null=True)
    phone = BooleanField(default=False, allow_blank=True, allow_null=True)


class User(Document):
    email = EmailField(required=True, max_length=200, unique=True)
    # regex '^\w+$' equals [a-zA-Z_]
    username = StringField(regex='^\w+$', required=True, max_length=15, min_length=3, unique=True)
    fullname = StringField(required=True, max_length=20)
    password = StringField(required=True)
    cover = StringField(default='')
    avatar = StringField(default='')
    dob = DateTimeField(default='')
    created_at = DateTimeField(default=datetime.datetime.utcnow())
    updated_at = DateTimeField(default=datetime.datetime.utcnow())
    bio = StringField(default='')
    location = StringField(default='')
    verification = EmbeddedDocumentField(Verification, required=True)
    account_type = StringField(required=True, default='regular', choices=('page', 'regular'))
    status = StringField(required=True, default='inactive', choices=('inactive', 'active', 'block'))
    phone = StringField(regex='^$|^[0-9()\\-\\.\\s]+$', default='')
2 Answers

exclude() and only() only effect what data is sent across the wire.

Fields will just show their defaults as attributes aren't stripped and there is no deferred loading.

Actually, this is a issue on github. See https://github.com/MongoEngine/mongoengine/issues/305

Related