djongo icon indicating copy to clipboard operation
djongo copied to clipboard

Embedded Model attributes not working

Open phacic opened this issue 6 years ago • 4 comments

Embedded Model fields attributes do not work

 class Blog(models.Model):
        name = models.CharField(max_length=100, db_index=True)
        tagline = models.TextField()
        image = models.ImageField(upload_to='upload/path')
        created = models.DateTimeField(auto_now_add=True)
        
        class Meta:
            abstract = True

 class Entry(models.Model):
        blog = models.EmbeddedModelField(
            model_container=Blog
        )
        headline = models.CharField(max_length=255)
        objects = models.DjongoManager()
  • Migration do not create index for blog.name. I ended up using a patch with pymongo thru Entry.objects to create the index
  • when creating a new entry with an embedded blog, no error is thrown but blog.created does not get the current date as expected of the auto_now_add attribute
  • also the image field does not upload image to specified path and that is the most worrying one cuz with the created field i could just override the save() of the entry to take care of that

So i can conclude that attributes on field of embedded model are not having any effects when creating the embedded document.

Can someone please provide a workaround especially for the image field

python 3.6 django 2.0.7 djongo 1.2.29

phacic avatar Jul 18 '18 17:07 phacic

I ended creating a custom EmbeddedModelField and overwriting the pre_save so that each fields pre_save will run

 def pre_save(self, model_instance, add):
        value = getattr(model_instance, self.attname)
        
        # go thru each field and and run its pre_save
        for fld in value._meta.get_fields():
            if not fields.useful_field(fld):
                continue

           # for date/datetime fields with auto_add_now when updating and the field value tend
            # to set to null when the incoming field value is not set.
            # we therefore have to set it to its original value so null is not inserted in the db
            if isinstance(fld, models.DateTimeField) or isinstance(fld, models.DateField):
                fld_value = getattr(value, fld.attname)
                if fld.auto_now_add and not add and not fld_value:
                    instance_model = type(model_instance)
                    initial = instance_model.objects.filter(pk=model_instance.pk).values_list(
                        self.attname, flat=True).first()
                    val = getattr(initial, fld.name)

                    # django already saves all dates in UTC so we might as well assume the date
                    # coming out is in UTC and if not tz info is provided to add it.
                    # works around django naive datetime warning
                    if not val.tzinfo:
                        val = pytz.UTC.fromutc(val)
                    setattr(value, fld.name, val)
                    continue

            fld.pre_save(value, add)

        if isinstance(value, fields.ModelSubterfuge):
            return value

        subterfuge = fields.ModelSubterfuge(value)
        return subterfuge

with this embedded fields attributes like auto_add_now, update_to work with exception of db_index which doesnt work yet cuz i guess it is used during migration.

If the creators could investigate the code above and factor a better version into the project it would be helpful

phacic avatar Jul 18 '18 21:07 phacic

@nesdis any comments on this issue??

eldano1995 avatar Mar 31 '20 22:03 eldano1995

I ended creating a custom EmbeddedModelField and overwriting the pre_save so that each fields pre_save will run

 def pre_save(self, model_instance, add):
        value = getattr(model_instance, self.attname)
        
        # go thru each field and and run its pre_save
        for fld in value._meta.get_fields():
            if not fields.useful_field(fld):
                continue

           # for date/datetime fields with auto_add_now when updating and the field value tend
            # to set to null when the incoming field value is not set.
            # we therefore have to set it to its original value so null is not inserted in the db
            if isinstance(fld, models.DateTimeField) or isinstance(fld, models.DateField):
                fld_value = getattr(value, fld.attname)
                if fld.auto_now_add and not add and not fld_value:
                    instance_model = type(model_instance)
                    initial = instance_model.objects.filter(pk=model_instance.pk).values_list(
                        self.attname, flat=True).first()
                    val = getattr(initial, fld.name)

                    # django already saves all dates in UTC so we might as well assume the date
                    # coming out is in UTC and if not tz info is provided to add it.
                    # works around django naive datetime warning
                    if not val.tzinfo:
                        val = pytz.UTC.fromutc(val)
                    setattr(value, fld.name, val)
                    continue

            fld.pre_save(value, add)

        if isinstance(value, fields.ModelSubterfuge):
            return value

        subterfuge = fields.ModelSubterfuge(value)
        return subterfuge

with this embedded fields attributes like auto_add_now, update_to work with exception of db_index which doesnt work yet cuz i guess it is used during migration.

If the creators could investigate the code above and factor a better version into the project it would be helpful

Hi, would you share the code?? There's some piece of it missing in your comment

eldano1995 avatar Mar 31 '20 22:03 eldano1995

Hi @eldano1995, I know it's an old issue. But, Im facing a bit similar issue, the embedded model with imagefield within it do not save the path of the content (and the content is not written into the disk) passed into it. Perhaps you found a fix before? Thank you.

prasetyaputraa avatar Nov 01 '21 06:11 prasetyaputraa