Джанго. Перезапис збереження для моделі


134

Перед збереженням моделі я перевстановлюю розмір зображення. Але як я можу перевірити, чи додано нове зображення чи оновлено лише опис, щоб я міг пропустити масштабування кожного разу, коли модель зберігається?

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)

Я хочу змінити масштаб лише в тому випадку, якщо завантажено нове зображення або оновлено зображення, але не після оновлення опису.


Ви змінюєте розмір до фіксованого розміру 100x100?
bdd

3
Ви можете вважати корисним django-imagekit
vikingosegundo

Відповіді:


135

Деякі думки:

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)

Не впевнений, чи добре це буде грати з усіма інструментами псевдоавтоматичного django (Приклад: ModelForm, contrib.admin тощо).


1
Виглядає добре. Але я не можу перейменувати зображення на _image. Це важливо?
Пол

Гаразд, я вирішив це за допомогою db_column = 'image'. Але це сталь не працює!
Пол

1
Це дуже цікавий метод .. я не розумію його повністю. Можете пояснити, будь ласка, більш експлікативно? Або посіяти якусь статтю?
Пол

Це також не працює для мене. set_image ніколи не дзвонив. Виглядає так, що деякі з Джанго офіційно не підтримують
Іван Борщов

16

Перевірте поле моделі ПК. Якщо це None, то це новий об'єкт.

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)

Редагувати: я додав чек на "зображення" у form.changed_data. Це передбачає, що ви використовуєте веб-сайт адміністратора для оновлення своїх зображень. Вам також доведеться замінити метод зберігання_модель за замовчуванням, як зазначено нижче.

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

Я думаю, ти маєш рацію ... припускаючи, що він використовує веб-сайт адміністратора, він може замінити save_model у своєму AdminModel, щоб передати форму для збереження та перевірити, чи є "image" у form.changed_data. Я оновлю, як тільки отримаю час.
DM Graves

Це працює лише в тому випадку, якщо об'єкт новий, як ви кажете. Якщо ви завантажите нову картинку, масштабування не запуститься.
Джонатан

2
"self.pk є None" не працює, якщо вказати ідентифікатор, тому: Model.objects.get_or_create (id = 234, ...) не працюватиме в цьому рішенні
гайки

6

Ви можете надати додатковий аргумент для підтвердження публікації нового зображення.
Щось на зразок:

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)

або передати змінну запиту

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)

Я думаю, що ці звички не порушують ваші заощадження, коли викликаються просто.

Ви можете помістити це у свою сторінку admin.py, щоб ця робота була і з сайтом адміністратора (для другого з вищезазначених рішень):

class ModelAdmin(admin.ModelAdmin):

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

він скаже мені, що: 'WSGIRequest' об’єкт не має атрибута 'FILE'
Пол

sry його FILES замість FILE, оновлений до request.FILES.get ('image', False) замість request.FILES ['image'], це дозволить уникнути виключення
crodjer

3

Що я зробив для досягнення мети - це досягти цього ..

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

і нижче метод save () - це ..

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

тому коли я редагую деякі поля, але не редагую зображення, я ставлю це ..

Model.save("skip creating photo thumbnail")

ви можете замінити "skip creating photo thumbnail"з "im just editing the description"або більш формальним текстом.

Сподіваюся, це допоможе!


2

Запросити в базу даних наявну запис із тим же ПК. Порівняйте розміри файлів і контрольні суми нових та існуючих зображень, щоб побачити, чи вони однакові.


1

Django 3: Переосмислення заздалегідь заданих методів

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)бізнес - щоб об'єкт все-таки зберігався в базі даних. Якщо ви забудете зателефонувати за методом суперкласу, поведінка за замовчуванням не відбудеться, і база даних не буде торкатися.


0

У новій версії він такий:

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

Я знайшов ще один простий спосіб зберігання даних у базі даних

models.py

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

У базі даних я лише 2 змінні

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

У цьому випадку я створив екземпляр моделі лише у views.py і вклав / зберігав дані у дві змінні лише з представлень даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.