Django anula guardar para el modelo solo en algunos casos?

6 minutos de lectura

Avatar de usuario de Pol
pol

Antes de guardar el modelo, cambio el tamaño de una imagen. Pero, ¿cómo puedo verificar si se agregó una nueva imagen o solo se actualizó la descripción, para poder omitir el cambio de escala cada vez que se guarda el modelo?

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if self.image:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

Quiero cambiar la escala solo si se carga una nueva imagen o se actualiza una imagen, pero no cuando se actualiza la descripción.

  • ¿Está cambiando el tamaño a un tamaño fijo de 100×100?

    – bdd

    24 de noviembre de 2010 a las 17:23

  • Puedes encontrar django-imagekit útil

    – vikingosegundo

    24 de noviembre de 2010 a las 18:12

  • Véanse también las notas en documentación.

    – djvg

    14/09/2022 a las 16:51


avatar de usuario de petraszd
petraszd

Algunos pensamientos:

class Model(model.Model):
    _image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()

    def set_image(self, val):
        self._image = val
        self._image_changed = True

        # Or put whole logic in here
        small = rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)

    def get_image(self):
        return self._image

    image = property(get_image, set_image)

    # this is not needed if small_image is created at set_image
    def save(self, *args, **kwargs):
        if getattr(self, '_image_changed', True):
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

No estoy seguro de si funcionaría bien con todas las herramientas pseudo-automáticas de django (Ejemplo: ModelForm, contrib.admin, etc.).

  • Se ve bien. Pero no puedo cambiar el nombre de la imagen a _image. ¿Es eso importante?

    – Pol

    24 de noviembre de 2010 a las 18:30

  • Ok, lo resolví con db_column=’image’. ¡Pero el acero no funciona!

    – Pol

    24 de noviembre de 2010 a las 18:34


  • Es un método muy interesante… por no entenderlo del todo. ¿Puedes explicarlo más explicativamente? ¿O sembrar algún artículo?

    – Pol

    24 de noviembre de 2010 a las 19:57


  • A mí tampoco me ha funcionado. set_image nunca llamó. Parece que esto es algo que Django no admite oficialmente.

    – Iván Borshchov

    8 abr 2017 a las 9:50


Avatar de usuario de DM Graves
Tumbas de DM

Compruebe el campo pk del modelo. Si es Ninguno, entonces es un objeto nuevo.

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if 'form' in kwargs:
            form=kwargs['form']
        else:
            form=None

        if self.pk is None and form is not None and 'image' in form.changed_data:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

Editar: he agregado un cheque para ‘imagen’ en form.changed_data. Esto supone que está utilizando el sitio de administración para actualizar sus imágenes. También tendrá que anular el método save_model predeterminado como se indica a continuación.

class ModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(form=form)

  • Creo que tiene razón… suponiendo que esté usando el sitio de administración, puede anular save_model en su AdminModel para pasar el formulario para guardarlo y verificar si la ‘imagen’ está en form.changed_data. Actualizaré en cuanto tenga tiempo.

    – DM Tumbas

    24 de noviembre de 2010 a las 20:10

  • Esto solo funciona si el objeto es nuevo como dices. Si carga una imagen nueva, no se activará el cambio de escala.

    – Jonathan

    8 de julio de 2014 a las 14:37

  • “self.pk is None” no funciona si se especifica el id, por lo que: Model.objects.get_or_create(id=234,…) no funcionará en esta solución

    – nueces

    10 de diciembre de 2014 a las 10:27


avatar de usuario de crodjer
crodjer

Puede proporcionar un argumento adicional para confirmar que se publica una nueva imagen.
Algo como:

def save(self, new_image=False, *args, **kwargs):
    if new_image:
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

o pasar la variable de solicitud

def save(self, request=False, *args, **kwargs):
    if request and request.FILES.get('image',False):
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

Creo que estos no romperán su ahorro cuando se llamen simplemente.

Puede poner esto en su admin.py para que funcione también con el sitio de administración (para la segunda de las soluciones anteriores):

class ModelAdmin(admin.ModelAdmin):

    ....
    def save_model(self, request, obj, form, change): 
        instance = form.save(commit=False)
        instance.save(request=request)
        return instance

  • me dice que: el objeto ‘WSGIRequest’ no tiene atributo ‘ARCHIVO’

    – Pol

    24 de noviembre de 2010 a las 18:01

  • sry sus ARCHIVOS en lugar de ARCHIVO, actualizado a solicitud.ARCHIVOS.get(‘imagen’, Falso) en lugar de solicitud.ARCHIVOS[‘image’]esto evitará la excepción

    – crodjer

    24 de noviembre de 2010 a las 18:03


Consultar la base de datos para un registro existente con el mismo PK. Compare los tamaños de archivo y las sumas de verificación de las imágenes nuevas y existentes para ver si son iguales.

Lo que hice para lograr el objetivo fue hacer esto..

# I added an extra_command argument that defaults to blank
def save(self, extra_command="", *args, **kwargs):

y debajo del método save() está esto …

# override the save method to create an image thumbnail
if self.image and extra_command != "skip creating photo thumbnail":
    # your logic here

entonces, cuando edito algunos campos pero no edito la imagen, pongo esto …

Model.save("skip creating photo thumbnail")

puedes reemplazar el "skip creating photo thumbnail" con "im just editing the description" o un texto más formal.

¡Espero que esto ayude!

Avatar de usuario de Fruchtzwerg
Fruchtzwerg

En la nueva versión es así:

def validate(self, attrs):
    has_unknown_fields = set(self.initial_data) - set(self.fields.keys())
    if has_unknown_fields:
        raise serializers.ValidationError("Do not send extra fields")
    return attrs

Avatar de usuario de Devendra Bhat
Devendra Bhat

He encontrado otra forma sencilla de almacenar los datos en la base de datos.

modelos.py

class LinkModel(models.Model):
    link = models.CharField(max_length=500)
    shortLink = models.CharField(max_length=30,unique=True)

En la base de datos solo tengo 2 variables.

vistas.py

class HomeView(TemplateView):
    def post(self,request, *args, **kwargs):
        form = LinkForm(request.POST)

        if form.is_valid():
            text = form.cleaned_data['link'] # text for link

        dbobj = LinkModel()
        dbobj.link = text
        self.no = self.gen.generateShortLink() # no for shortLink
        dbobj.shortLink = str(self.no)
        dbobj.save()         # Saving from views.py

En esto, he creado la instancia del modelo solo en views.py y he puesto/guardado datos en 2 variables solo desde las vistas.

¿Ha sido útil esta solución?