Обновление поля Django ImageField через .update() ORM

Подобные вопросы были заданы здесь:

Но ответ всегда был один и тот же ("используйте .save() вместо этого") - это решение работает , но из-за сигналов на модели, которые я не могу контролировать, я хотел бы знать, есть ли какие-либо обходные пути, которые можно использовать вместо этого.

# serializers.py

from drf_extra_fields.fields import Base64ImageField
from rest_framework import serializers


class ProfileSerializer(serializers.Serializer):
    email = serializers.CharField(required=False, allow_null=True)
    image = Base64ImageField(required=False, allow_null=True, max_length=None, use_url=True)

# views.py

def get_as_base64(url: AnyStr):
    if url is None:
        return None, None
    full_name = url.split("/")[-1]
    my_base = base64.b64encode(requests.get(url).content)
    return my_base, full_name

def do_profile_update(profile: Dict):
    b64_image, file_name = get_as_base64(profile.get("url"))
    if b64_image and file_name:
        *_, file_ext = file_name.split(".")
        b64_image = f"data:image/{file_ext};base64,{b64_image.decode('utf-8')}"

    build_dict = {
        "email": profile.get("email"),
        "image": b64_image,
    }
    serializer = ProfileSerializer(data=build_dict)
    serializer.is_valid()  # returns True
    # serializer.validated_data = {'email': 'test@example.org', 'image': <SimpleUploadedFile: 11735acf-6d96-4c62-9e6a-8ebb7f7ea509.jpg (image/jpeg)>}
    Profile.objects.filter(pk=pk).update(**serializer.validated_data)  # This saves the *name* of the image to the database, but no image file

Я понимаю, что ImageField - это по сути CharField, и я могу видеть name изображения в базе данных, но изображение не записывается на сервер.

Мой вопрос сводится к следующему: есть ли способ отдельно записать изображение на сервер, получить путь к новому сохраненному изображению и использовать его в .update()?

TYIA.

Вы можете сохранить свой файл отдельно на медиа-сервере с помощью класса django DefaultStorage (см. docs).

import os
import io
import requests
from django.conf import settings
from django.core.files.images import ImageFile
from django.core.files.storage import default_storage

response = requests.get(url)
full_name = url.split("/")[-1]
img_path = os.path.join(settings.MEDIA_ROOT, full_name)
image = ImageFile(io.BytesIO(response.content))
default_storage.save(img_path, image)
Вернуться на верх