Django. Ganti simpan untuk model

134

Sebelum menyimpan model, saya mengubah ukuran gambar. Tetapi bagaimana saya bisa mengecek apakah gambar baru ditambahkan atau hanya deskripsi yang diperbarui, sehingga saya dapat melewati penyetelan ulang setiap kali model disimpan?

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)

Saya ingin mengubah skala hanya jika gambar baru dimuat atau gambar diperbarui, tetapi tidak ketika deskripsi diperbarui.

Pol
sumber
Apakah Anda mengubah ukuran ke ukuran tetap 100x100?
bdd
3
Kamu mungkin menemukan django-imagekit berguna
vikingosegundo

Jawaban:

135

Beberapa pemikiran:

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)

Tidak yakin apakah itu akan bermain bagus dengan semua alat django pseudo-otomatis (Contoh: ModelForm, contrib.admin dll).

petraszd
sumber
1
Terlihat bagus. Tapi saya tidak bisa mengganti nama gambar menjadi _image. Apakah itu penting?
Pol
Ok saya menyelesaikannya dengan db_column = 'image'. Tapi itu baja tidak berfungsi!
Pol
1
Ini metode yang sangat menarik .. oleh saya tidak mengerti sepenuhnya. Bisakah Anda menjelaskannya lebih jelas? Atau menabur beberapa artikel?
Pol
Itu tidak bekerja untuk saya juga. set_image tidak pernah menelepon. Sepertinya ini beberapa hal Django yang tidak didukung secara resmi
Ivan Borshchov
16

Periksa bidang pk model. Jika tidak ada, maka itu adalah objek baru.

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)

Sunting: Saya telah menambahkan tanda centang untuk 'gambar' di form.changed_data. Ini mengasumsikan bahwa Anda menggunakan situs admin untuk memperbarui gambar Anda. Anda juga harus mengganti metode save_model default seperti yang ditunjukkan di bawah ini.

class ModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(form=form)
Kuburan DM
sumber
Saya pikir Anda benar ... dengan asumsi ia menggunakan situs admin, ia dapat mengganti save_model di AdminModel untuk meneruskan formulir untuk menyimpan, dan memeriksa apakah 'gambar' ada di form.changed_data. Saya akan memperbarui segera setelah saya punya waktu.
DM Graves
Ini hanya berfungsi jika objek tersebut baru seperti yang Anda katakan. Jika Anda mengunggah gambar baru, pemasangan ulang tidak akan memicu.
Jonathan
2
"self.pk is None" tidak berfungsi jika seseorang menentukan id, jadi: Model.objects.get_or_create (id = 234, ...) tidak akan berfungsi dalam solusi ini
kacang
6

Anda dapat memberikan argumen tambahan untuk mengonfirmasi gambar baru diposkan.
Sesuatu seperti:

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)

atau lulus variabel permintaan

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)

Saya pikir ini tidak akan merusak tabungan Anda ketika dipanggil sederhana.

Anda dapat meletakkan ini di admin.py Anda sehingga ini berfungsi dengan situs admin juga (untuk solusi kedua di atas):

class ModelAdmin(admin.ModelAdmin):

    ....
    def save_model(self, request, obj, form, change): 
        instance = form.save(commit=False)
        instance.save(request=request)
        return instance
crodjer
sumber
itu memberi tahu saya bahwa: objek 'WSGIRequest' tidak memiliki atribut 'FILE'
Pol
sry FILES-nya bukan FILE, perbarui untuk request.FILES.get ('image', False) alih-alih request.FILES ['image'], ini akan menghindari pengecualian
crodjer
3

Apa yang saya lakukan untuk mencapai tujuan adalah membuat ini ..

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

dan di bawah metode save () adalah ini ..

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

jadi ketika saya mengedit beberapa bidang tetapi tidak mengedit gambar, saya taruh ini ..

Model.save("skip creating photo thumbnail")

Anda dapat mengganti "skip creating photo thumbnail"dengan "im just editing the description"atau dengan teks yang lebih formal.

Semoga yang ini membantu!

bonbon.langes
sumber
2

Permintaan database untuk catatan yang ada dengan PK yang sama. Bandingkan ukuran file dan checksum dari gambar baru dan yang ada untuk melihat apakah mereka sama.

Ignacio Vazquez-Abrams
sumber
1

Django 3: Mengganti metode model yang sudah ditentukan sebelumnya

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, *args, **kwargs):
        do_something()
        super().save(*args, **kwargs)  # Call the "real" save() method.
        do_something_else()

Penting untuk diingat untuk memanggil metode superclass - itu super().save(*args, **kwargs)bisnis itu - untuk memastikan bahwa objek masih disimpan ke dalam database. Jika Anda lupa memanggil metode superclass, perilaku default tidak akan terjadi dan database tidak akan tersentuh.

panchicore
sumber
0

Dalam versi baru seperti ini:

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

Saya telah menemukan satu sama lain cara sederhana untuk menyimpan data ke dalam basis data

models.py

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

Dalam database saya hanya memiliki 2 variabel

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

Dalam hal ini saya telah membuat contoh model hanya dalam views.py dan menempatkan / menyimpan data menjadi 2 variabel dari hanya dilihat.

Devendra Bhat
sumber