Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling certain functions when initializing a new mongoengine document

I'm trying to define a Document class that has some fields that have their values automatically calculated when a new document is created. So far I have succeeded in doing that by extending the __init__ function like this:

class URLDoc(Document):
    url = fields.URLField(requierd=True)
    domain = fields.StringField(required=True)
    screenshot = fields.ImageField(required=True, size=(600, 600, True), thumbnail=(100, 100, True))

    def __init__(self, *args, **kwargs):
        super(URLDoc, self).__init__(*args, **kwargs)
        self.domain = urlparse(self.url).netloc
        self.get_and_save_screenshot()


    def get_and_save_screenshot(self):
        '''Some code to get a screenshot of the website on self.url'''

        self.screenshot.put(screenshot_file)
        self.save()

This way I was able to create new documents in mongo by just calling new_urldoc = URLDoc(url="some url") and then just new_urldoc.save().

When I started loading existing documents from mongo by URLDoc.objects.get(id="some id") I realized that the __init__ function will be triggered again set new data (take a new screenshot for example) in the document.

I want to implement this but only when the document is new, I looked up everywhere and couldn't find an answer..

Is there a way to call certain functions when initializing a new document as opposed to initializing an existing document?

like image 346
guysh Avatar asked Oct 17 '25 14:10

guysh


2 Answers

I was looking for a similar solution and after a while I found that MongoEngine supports Signals. There are multiple signals that can be coupled with document before/after certain operations:

  • initialization
  • saving
  • deletion

Unfortunately is does not support signals based on document update, but a workaround it is to check if the sender document has an id or not. A simple snippet code - based on the example in the MongoEngine documentation:

def update_modified(sender, document):
    if document.id: 
        document.modified = datetime.utcnow() # Will only be executed if the document has been already saved
like image 153
Mosallamy Avatar answered Oct 20 '25 03:10

Mosallamy


Based on mongoengine's documentations, You can make sure a document is being loaded from the database if the _created kwarg is passed as True like this:

    def __init__(self, your_var, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(kwargs)
        if not kwargs.get('_created', True):
            return  # Loaded from DB, No modification needed
        self.some_var = your_var
        # Initiate the brand new instance

note: this method that's been mentioned before does work, but only for Documents. EmbeddedDocuments do not have the id attribute!

if self.id: 
    print("loaded from DB")
else:
    print("Brand new instance!")
like image 28
Saee Saadat Avatar answered Oct 20 '25 02:10

Saee Saadat