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.


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).


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)

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

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!


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.


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.


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

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.