web-dev-qa-db-fra.com

Django. Remplacer enregistrer pour le modèle

Avant de sauvegarder le modèle, je redimensionne une image. Mais comment puis-je vérifier si une nouvelle image a été ajoutée ou si une description a été mise à jour, afin que je puisse éviter de redimensionner chaque fois que le modèle est enregistré?

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)

Je veux redimensionner uniquement si une nouvelle image est chargée ou une image mise à jour, mais pas lorsque la description est mise à jour.

100
Pol

Quelques idées:

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)

Je ne sais pas si cela pourrait jouer à Nice avec tous les outils pseudo-automatiques de Django (exemple: ModelForm, contrib.admin, etc.).

108
petraszd

Vérifiez le champ pk du modèle. Si c'est Aucun, alors c'est un nouvel objet.

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)

Edit: j'ai ajouté une vérification pour 'image' dans form.changed_data. Cela suppose que vous utilisez le site administrateur pour mettre à jour vos images. Vous devrez également remplacer la méthode save_model par défaut, comme indiqué ci-dessous.

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

Vous pouvez fournir un argument supplémentaire pour confirmer qu'une nouvelle image est publiée.
Quelque chose comme:

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)

ou passer la variable de demande

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)

Je pense que ceux-ci ne briseront pas votre sauvegarde quand ils sont appelés simplement.

Vous pouvez le mettre dans votre fichier admin.py pour que cela fonctionne également avec le site admin (pour les solutions suivantes):

class ModelAdmin(admin.ModelAdmin):

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

Ce que j’ai fait pour atteindre cet objectif a été de rendre cela ..

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

et en dessous de la méthode save () est ceci ..

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

alors, quand je modifie des champs sans éditer l'image, je mets ceci ..

Model.save("skip creating photo thumbnail")

vous pouvez remplacer le "skip creating photo thumbnail" par "im just editing the description" ou un texte plus formel.

J'espère que cela aide!

2
bonbon.langes

Interrogez la base de données pour un enregistrement existant avec le même PK. Comparez les tailles de fichier et les sommes de contrôle des images nouvelles et existantes pour voir si elles sont identiques.

1

J'ai trouvé un autre moyen simple de stocker les données dans la base de données

models.py

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

Dans la base de données je n'ai que 2 variables

views.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 cela, j'ai créé l'instance de modèle dans views.py uniquement et en plaçant/sauvegardant des données dans 2 variables à partir de vues uniquement.

0
Devendra Bhat

Dans la nouvelle version c'est comme ça: 

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
0
Dan Goriaynov