Search code examples
pythonmongoengine

In Mongoengine add a document and update a reference field in another document


I have two documents and I would like to link together through a reference Field using the _ID. The idea was to create the documents, save them to the database, take the _ID information and append it to a reference list of another document. As the documents will be created at different times, I cannot have both established before hand.

Here is the code thus far and the error that occurs.

from mongoengine import StringField, Document, DateField, ReferenceField

class GameWrapper(Document)
     title: StringField()
     year: DateField()

class GameCompanyWrapper(Document):
     Company_Name: StringField()
     published_games: ReferenceField(GameWrapper)

class IstrumentService:
    mongo_url: str = None 

    def save(self, inst: GameWrapper) -> ObjectId:
        saved_inst: inst = inst.save()
        return saved_inst.id

instrument_service = IstrumentService()

GCW = GameCompanyWrapper()
GCW.Company_Name = "Squaresoft"
IstrumentService.save(GCW)

GW = GameWrapper()
GW.Title = "Final Fantasy"
ob_ID = IstrumentService.save(GCW)

GCW.published_games = ob_ID
IstrumentService.save(GW)

AttributeError: 'ObjectId' object has no attribute '_data'

I am under the assumption that the objectID is a reference to an entry in the database, so why does it throw a no attribute '_data' error?


Solution

  • You must save GW before assign it to GCW. In your code:

    GW = GameWrapper()
    GW.Title = "Final Fantasy"
    ob_ID = IstrumentService.save(GCW)
    

    GW is created object GW but it didn't save to db so it doesn't have object Id. Now, Your ob_ID is GCW, after that you assign this Id to GCW.published_games and save GW. This stuck between GW and GCW.

    I rewrited your code, and it worked. Save GW before assign to GCW

        instrument_service = IstrumentService()
        GCW = GameCompanyWrapper()
        GCW.Company_Name = "Squaresoft"
        instrument_service.save(GCW)
    
        GW = GameWrapper()
        GW.title = "Final Fantasy"
        ob_ID = instrument_service.save(GW)
    
        GCW.published_games = ob_ID
        instrument_service.save(GCW)