MongoEngine / mongoengine

A Python Object-Document-Mapper for working with MongoDB
http://mongoengine.org
MIT License
4.24k stars 1.23k forks source link

copy.deepcopy fails on mongoengine object #993

Open dmitry-saritasa opened 9 years ago

dmitry-saritasa commented 9 years ago
self.shift = Shift.objects.get(id=shift_id)
self.presave = copy.deepcopy(self.shift)

throws the error:
#1091 self.error('Only accept a document object') in to_mongo() method of CachedReferenceField class defined in mongonengine/fields.py

this is my debugger:
http://snag.gy/svEOT.jpg

*my model:*

``` python
class Shift(Document):  
    parent      = ReferenceField('Shift')  # shift parent ID, if we have type=reschedule or reassigned
    type        = StringField(max_length=50, required=True, choices=['regular', 'holiday', 'newshift', 'reschedule', 'reassignment'])
    date        = DateTimeField() #only if exception is created
    school      = ReferenceField(School, required=True)
    location    = ReferenceField(Location, required=True)
    guard       = ReferenceField(Guard, required=True) #only if exception is created
    name        = StringField(max_length=255)
    weekday     = IntField(required=True, min_value=1, max_value=7)  # isoweekday, Monday = 1
    start       = TimeField(required=True)
    finish      = TimeField(required=True)
    start_sec   = IntField(required=True)
    finish_sec  = IntField(required=True)
    weight      = IntField(required=True) # used for sorting - this is hh_mm_ss for local of this school timezone
    holidays    = ListField(DateTimeField()) # only for regular shift, let's not create a custom exception for each holiday date
    comment     = StringField(max_length=2000)
    created_at  = DateTimeField()
    updated_at  = DateTimeField()
    deactivated_at = DateTimeField()

    # speed up fields
    guard_name  = StringField(max_length=515)
    guard_phone = StringField(max_length=255)
    school_name = StringField(max_length=255)
    location_name = StringField(max_length=255)
    parent_cache = CachedReferenceField('Shift', fields=['type', 'start', 'finish', 'start_sec', 'finish_sec', 'guard', 'weight'])

    @property
    def assigned_guard(self):
        return self.guard

    @property
    def holiday(self):
        if self.date in self.holidays:
            return True
        return False

    def confirmations(self, date=None):
        if date:
            return Confirmation.objects(date=date, shift=self)
        else:
            return Confirmation.objects(shift=self)

    def exceptions(self, date=None):
        """

        :param date: should be of datetime.date type
        :return:
        """
        if self.parent:
            return list()

        if isinstance(date, datetime.date):
            date = todatetime(date)

        if date:
            return Shift.objects(parent=self, date=date)
        else:
            return Shift.objects(parent=self)

    def notify(self, message=None, guard=None, type=None):
        """
        Used to notify guard about new shift assigned to him
        """
        from bll.mobile_notifications import ShiftPushNotification
        ShiftPushNotification(self, message=message, guard=guard, type=type).send()    

    def delete(self, *args, **kwargs):
        """
        Override delete method, so that we mark that physical record in DB as deactivated_at
        instead of physically removing it
        also send DELETE signal for other collections to handle CASCADE/NULLIFY properly
        """
        self.deactivated_at = datetime.datetime.now()
        signals.pre_delete.send(self.__class__, document=self)
        return super(Shift, self).save(*args, **kwargs)

    def to_json(self):
        return {
            'id': self.id,
            'guard': self.guard,
            'name': self.name,
            'start': self.start,
            'finish': self.finish,
            'weekday': self.weekday,
            'type': self.type
        }

    def __str__(self):
        return str(self.id)

    meta = {
        'indexes': [
            {'fields': ['+name']},
            {'fields': ['+date', 'location']},
            {'fields': ['+date','+school', '+location']},
            {'fields': ['+location']},
            {'fields': ['+guard']},
            {'fields': ['+parent']},
            {'fields': ['+parent_cache.guard']},
        ]
    }
dmitry-saritasa commented 9 years ago

Sample data is

{
    "_id" : ObjectId("554ad0c18a5da50025b7c7c3"),
    "parent" : ObjectId("55241c448a5da5002616ede5"),
    "type" : "reassignment",
    "date" : ISODate("2015-05-08T00:00:00.000Z"),
    "school" : ObjectId("55241a8983ba889a678b4567"),
    "location" : ObjectId("55241ae583ba88d46c8b4567"),
    "guard" : ObjectId("55355d7083ba88e23f8b4569"),
    "name" : "1st shift",
    "weekday" : 5,
    "start" : "08:00:00",
    "finish" : "08:30:00",
    "start_sec" : 28800,
    "finish_sec" : 30600,
    "weight" : 28800,
    "holidays" : [],
    "created_at" : ISODate("2015-05-07T02:41:05.618Z"),
    "updated_at" : ISODate("2015-05-07T00:10:20.982Z"),
    "guard_name" : "Guard2Vadik alt Kuz",
    "school_name" : "VictorHigh",
    "location_name" : "Joslin / Gard",
    "parent_cache" : {
        "_id" : ObjectId("55241c448a5da5002616ede5"),
        "finish" : "08:30:00",
        "weight" : 28800,
        "start_sec" : 28800,
        "finish_sec" : 30600,
        "start" : "08:00:00",
        "guard" : ObjectId("552411f883ba8842658b4567"),
        "type" : "regular"
    }
}
AlexanderPease commented 8 years ago

we have similar issues.