Хотите загрузить изображение с помощью пользовательской функции загрузки изображения python djano

Это моя пользовательская функция загрузки изображений

def upload_image(file, dir_name, filename):
    try:
        target_path = '/static/images/' + dir_name + '/' + filename
        path = storage.save(target_path, file)
        return storage.url(path)
    except Exception as e:
        print(e)

а это моя модель

class MenuOptions(models.Model):
    name = models.CharField(max_length=500, null=False)
    description = models.CharField(max_length=500, null=True)
    image_url = models.ImageField(upload_to=upload_image())

    def __str__(self):
        return f'{self.name}'

Я хочу загрузить изображение с помощью моей функции upload_image, и, как вы видите, она принимает 3 параметра file, dir_name и имя_файла. Как я могу передать эти параметры в model.ImageField()? Также я хочу сохранить image_url в моей базе данных, как возвращается функцией upload_image, будет ли она сохранять файл в БД или URL?

Прежде всего, вы должны передать upload_image, а не вызов upload_image():

image_url = models.ImageField(upload_to=upload_image)

Во-вторых, upload_to автоматически вызывает Storage.save() с переданным значением. Поэтому вызов внутри upload_image() не нужен. upload_image должен возвращать только путь, по которому должен быть сохранен файл.

функция upload_to должна принимать 2 параметра, instance и filename.

ссылка

Вот мое решение для хранения файлов.

Вы просто реализуете приведенную ниже функцию и используете ее в модели.

import os
import uuid
from django.utils.deconstruct import deconstructible


@deconstructible
class MediaFileNameHash(object):
    def __init__(self, base_dir, path):
        self.address = base_dir + "/" + path
        self.path = path
        if not os.path.exists(self.address):
            os.makedirs(self.address, exist_ok=True)

    def __call__(self, _, filename):
        # @note It's up to the validators to check if it's the correct file type in name or if one even exist.
        filename = os.path.splitext(filename)
        return self.path + '/' + filename[0] + "@" + str(uuid.uuid4()) + filename[1]

например:

class MenuOptions(models.Model):
    name = models.CharField(max_length=500, null=False)
    description = models.CharField(max_length=500, null=True)
    image_url = models.ImageField(
         upload_to=MediaFileNameHash("/media/", "files"),
         verbose_name=_("Address")
    )

Для того, чтобы передать имя функции, сначала нужно написать функцию в модели, которая обрабатывает путь, вот так !

# In you models.py 
# will automatically save your image to your custom view 

def get_upload_image_filepath(self, filename):
    return 'Images/' + str(self.pk) + '/default.png'

class MenuOptions(models.Model):
    name = models.CharField(max_length=500, null=False)
    description = models.CharField(max_length=500, null=True)
    image_url = models.ImageField(upload_to=get_upload_image_filepath)

    def __str__(self):
        return f'{self.name}'

Ну, я просто собираюсь подсказать вам, как вы можете поступить в этой ситуации, вы можете рефакторить свой код, так как это будет работать в том же смысле. вот мое решение о том, как написать свой пользовательский вид:

# this would be at the top of your view 
import base64
import os

TEMP_UPLOAD_IMAGE_NAME = "default.png"


def save_temp_upload_image_from_base64String(imageString, user):
    INCORRECT_PADDING_EXCEPTION = "Incorrect padding"
    try:
        if not os.path.exists(settings.TEMP):
            os.mkdir(settings.TEMP)
        if not os.path.exists(settings.TEMP + "/" + str(user.pk)):
            os.mkdir(settings.TEMP + "/" + str(user.pk))
        url = os.path.join(settings.TEMP + "/" + str(user.pk),TEMP_UPLOAD_IMAGE_NAME)
        storage = FileSystemStorage(location=url)
        image = base64.b64decode(imageString)
        with storage.open('', 'wb+') as destination:
            destination.write(image)
            destination.close()
        return url
    except Exception as e:
        print("exception: " + str(e))
        # workaround for an issue I found
        if str(e) == INCORRECT_PADDING_EXCEPTION:
            imageString += "=" * ((4 - len(imageString) % 4) % 4)
            return save_temp_upload_image_from_base64String(imageString, user)
    return None
Вернуться на верх