ivica
ivica

Reputation: 1428

mongoengine default value from another field

I'm trying out MongoEngine for a project and its quite good. I was wondering if it is possible to set a default value for a field from another field? Something like this

import mongoengine as me

class Company(me.Document):
    short_name = me.StringField(required=True)
    full_name = me.StringField(required=True, default=short_name)

this fails with an error ValidationError (Company:None) (StringField only accepts string values: ['full_name'])

:EDIT:

I did not mention that my app has a service layer which enabled me to simply do it like this:

if company_data['short_name'] is None:
            myCompany.full_name = company_data['short_name']


        obj = myCompany.save()

and it works quite nicely.

Upvotes: 6

Views: 7847

Answers (3)

Allan Lei
Allan Lei

Reputation: 328

default does not get passed the instance of the document, so you won't be able to achieve what you want.

The save solution is ok, but the value of full_name is not set until there is a save() called.

Instead, use mongoengine's post_init signal

@mongonegine.post_init.connect_via(Company)
def set_full_name(sender, document, **kwargs):
    document.full_name = document.full_name or document.short_name
  • Works for new inits and documents from queries
  • The defaulted value is available immediately after init.
    Company(short_name='hello').full_name' == 'hello'
    

Upvotes: 0

hamidfzm
hamidfzm

Reputation: 4685

Take a look at http://docs.mongoengine.org/guide/defining-documents.html#field-arguments:

You can achieve this by passing a function to default property of the field:

class ExampleFirst(Document):
    # Default an empty list
    values = ListField(IntField(), default=list)

class ExampleSecond(Document):
    # Default a set of values
    values = ListField(IntField(), default=lambda: [1,2,3])

class ExampleDangerous(Document):
    # This can make an .append call to  add values to the default (and all the following objects),
    # instead to just an object
    values = ListField(IntField(), default=[1,2,3])

Upvotes: 4

alecxe
alecxe

Reputation: 473993

You can override save() method on a Document:

class Company(me.Document):
    short_name = me.StringField(required=True)
    full_name = me.StringField()

    def save(self, *args, **kwargs):
        if not self.full_name:
            self.full_name = self.short_name

        return super(Company, self).save(*args, **kwargs)

Upvotes: 11

Related Questions