A
A
Alexander Vinogradov2017-02-28 19:46:23
Django
Alexander Vinogradov, 2017-02-28 19:46:23

How to save the result of changing the value in the database?

In the model, I override the save function. If I make a change to the value of a field, for example, self.imagepath.name = new_db_imagepath, then this change must be saved. If you save the changes, as it is written in the djangobook examples, i.e. self.save() then the whole process will hang. Then, to save, I substituted super(Images, self).save(*args, **kwargs) and got what I needed.
So why is self.save() looping and what is the correct way to save changes?

class Images(models.Model):
    '''Таблица путей изображений'''
    furnproduct = models.ForeignKey(FurnitureProduct, on_delete=models.CASCADE, verbose_name='Изделие')
    imagepath = models.ImageField(upload_to=PathAndRename('images'), verbose_name='Изображение')
    
    def save(self, *args, **kwargs):
        # Сначала - обычное сохранение
        super(Images, self).save(*args, **kwargs)
        
        # Проверяем, указана ли картинка
        if self.imagepath:
            filepath = self.imagepath.path
            dirpath = os.path.dirname(filepath)
            ext = filepath.split('.')[-1]
            new_file_name = '{}.{}'.format(self.pk, ext)
            db_imagepath = self.imagepath.name
            list_imagepath = db_imagepath.split('/')[:-1]
            list_imagepath.append(new_file_name)
            new_db_imagepath = '/'.join(list_imagepath)
            
            width = self.imagepath.width
            height = self.imagepath.height
            ratio = width/height
            # Может, и не надо ничего менять?
            if (width > MAX_WIDTH_IMAGE) or (height > MAX_HEIGHT_IMAGE):
                
                image = Image.open(filepath)
                # resize - безопасная функция, она создаёт новый объект, а не
                # вносит изменения в исходный, поэтому так
                if ratio > 1:
                    image = image.resize((MAX_WIDTH_IMAGE, round(MAX_WIDTH_IMAGE/ratio)), Image.ANTIALIAS)
                else:
                    image = image.resize((round(MAX_HEIGHT_IMAGE*ratio), MAX_HEIGHT_IMAGE), Image.ANTIALIAS)
                
                image.save(os.path.join(dirpath, new_file_name))
                self.imagepath.name = new_db_imagepath
                super(Images, self).save(*args, **kwargs)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Abdulla Mursalov, 2017-03-01
@amaprograma

Meet Recursion:

def foo():
    foo()

Method overriding:
class Bar():
    def foo(self, ...):
        pass

class Foo(Bar):
    ...
    def foo(self, ...):
        super(Foo, self).foo(...)
        pass

Another way to fall into recursion:
class Foo(models.Model):
    ...
    pass

@receiver(post_save, sender=Foo)
def foo_bar(sender, instance, **kwargs):
    instance.save()

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question