Django. Model için kaydetmeyi geçersiz kıl


134

Modeli kaydetmeden önce bir resmi yeniden boyutlandırıyorum. Ancak, yeni resmin eklenip eklenmediğini veya sadece açıklamanın güncellendiğini nasıl kontrol edebilirim, böylece model her kaydedildiğinde yeniden ölçeklemeyi atlayabilirim?

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)

Yalnızca yeni görüntü yüklendiğinde veya görüntü güncellendiğinde yeniden ölçeklendirmek istiyorum, ancak açıklama güncellendiğinde değil.


100x100'lük sabit bir boyuta mı yeniden boyutlandırıyorsunuz?
bdd

3
Django-imagekit'i faydalı bulabilirsin
vikingosegundo

Yanıtlar:


135

Bazı düşünceler:

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)

Tüm sözde otomatik django araçlarıyla iyi oynayıp oynamayacağından emin değilim (Örnek: ModelForm, Contrib.admin vb.).


1
Güzel gözüküyor. Ancak görüntüyü _image olarak yeniden adlandıramıyorum. Önemli mi?
Pol

Tamam db_column = 'image' ile çözdüm. Ama çelik işe yaramıyor!
Pol

1
Bu çok ilginç bir yöntem .. tam olarak anlamıyorum. Lütfen daha açık bir şekilde açıklar mısınız? Veya bir makale mi ekmek?
Pol

Benim için de çalışmadı. set_image aramadı. Bu bazı Django gibi görünüyor resmen şeyler desteklenmemektedir
Ivan Borshchov

16

Modelin pk alanını kontrol edin. Yok ise, yeni bir nesnedir.

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)

Düzenleme: form.changed_data'ya 'image' için bir kontrol ekledim. Bu, resimlerinizi güncellemek için yönetici sitesini kullandığınızı varsayar. Ayrıca, aşağıda belirtildiği gibi varsayılan save_model yöntemini de geçersiz kılmanız gerekir.

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

Sanırım haklısın ... yönetici sitesini kullandığını varsayarsak, formu kaydetmek için AdminModel'inde save_model'i geçersiz kılabilir ve 'image'ın form.changed_data'da olup olmadığını kontrol edebilir. Zamanı bulur bulmaz güncelleme yapacağım.
DM Graves

Bu yalnızca, nesne söylediğiniz gibi yeniyse çalışır. Yeni bir resim yüklerseniz, yeniden ölçeklendirme tetiklenmez.
Jonathan

2
Bir id belirtilirse "self.pk Yoktur" çalışmaz, bu nedenle: Model.objects.get_or_create (id = 234, ...) bu çözümde çalışmaz
fındık

6

Yeni bir görüntünün gönderildiğini onaylamak için ekstra argüman sağlayabilirsiniz.
Gibi bir şey:

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)

veya istek değişkenini geç

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)

Bence bunlar basitçe çağrıldığında tasarrufunuzu bozmaz.

Bunu, yönetici sitesinde de çalışması için admin.py dosyanıza koyabilirsiniz (yukarıdaki çözümlerin ikincisi için):

class ModelAdmin(admin.ModelAdmin):

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

bana şunu söylüyor: 'WSGIRequest' nesnesinin 'FILE' özniteliği yok
Pol

sry, FILE yerine FILES, request.FILES.get ('image', False) yerine request.FILES ['image'] olarak güncellendi, bu istisnayı önleyecek
crodjer

3

Hedefe ulaşmak için yaptığım şey bunu yapmaktı ..

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

ve save () yönteminin altında bu ..

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

bu yüzden bazı alanları düzenleyip resmi düzenlemediğimde, bunu koyuyorum ..

Model.save("skip creating photo thumbnail")

Eğer yerini alabilir "skip creating photo thumbnail"ile "im just editing the description"veya daha resmi metni.

Umarım bu yardımcı olur!


2

Aynı PK'ye sahip mevcut bir kayıt için veritabanını sorgulayın. Aynı olup olmadıklarını görmek için yeni ve mevcut görüntülerin dosya boyutlarını ve sağlama toplamlarını karşılaştırın.


1

Django 3: Önceden tanımlanmış model yöntemlerini geçersiz kılma

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

super().save(*args, **kwargs)Nesnenin veritabanına hala kaydedildiğinden emin olmak için süper sınıf yöntemini çağırmayı hatırlamak önemlidir - işte bu iş -. Üst sınıf yöntemini çağırmayı unutursanız, varsayılan davranış gerçekleşmez ve veritabanına dokunulmaz.


0

Yeni versiyonda şöyle:

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

Verileri veritabanına depolamanın başka bir basit yolunu buldum

models.py

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

Veritabanında sadece 2 değişkenim var

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

Bunda, model örneğini yalnızca views.py'de oluşturdum ve verileri yalnızca görünümlerden 2 değişkene koyarak / kaydettim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.