您现在的位置是: 网站首页> 学习笔记> Django Django

django使用自定义存储类上传图片到阿里OSS,makemigrations时报异常

2024-07-31 [django] 236人已围观

自定义了一个存储类,用于上传图片到阿里OSS,类如下:

from django.core.files.storage import Storage
from cloudstorage.alioss import alioss
import time
import logging
import uuid
from orderingshop.settings import ALI_OSS_ACCESS_DOMAIN

logger = logging.getLogger(__name__)


class OssStorage(Storage):

    def __init__(self, upload_to: str = ""):
        self.upload_to = upload_to
        self.path_str = upload_to
        if not upload_to.endswith("/"):
            self.path_str = self.path_str + "/"
        self.res = None

    def save(self, name, content, max_length=None):
        """
     文件保存
     :param name: 上传时的文件名称,包含后缀名
     :param content: 文件内容,File对象
     :param max_length: 文件最大二进制长度
     :return: 文件路径
     """
        _date = time.strftime('%Y-%m-%d')
        self.path_str = self.path_str + _date + '/' + '{}.{}'.format(uuid.uuid4(), name.split('.')[-1])
        res = alioss.upload(self.path_str, content)
        self.res = res
        return self.path_str

    def delete(self, name):
        """
        删除文件
        :param name: 相对路径文件名,此处并非上传时的文件名,而是在save()函数中返回的文件名
        :return:
        """
        try:
            alioss.delete(name)
        except Exception as e:
            logger.error('删除文件失败,error: {}'.format(e))

    def url(self, name):
        """
        返回文件的url地址
        :param name: 相对路径文件名,此处并非上传时的文件名,而是在save()函数中返回的文件名
        :return:
        """
        return f'{ALI_OSS_ACCESS_DOMAIN}{"" if ALI_OSS_ACCESS_DOMAIN.endswith("/") else "/"}{name}'

    def path(self, name):
        """
        返回文件的相对路径地址
        :param name: 相对路径文件名,此处并非上传时的文件名,而是在save()函数中返回的文件名
        :return: 相对路径地址
        """

        return name

    def open(self, name, mode='rb'):
        """
        打开文件操作,一般pass即可
        :param name: 相对路径文件名,此处并非上传时的文件名,而是在save()函数中返回的文件名
        :param mode: 打开方式,默认'rb'
        :return:
        """
        pass

使用方式:

class MainImage(SiteBaseModel):
    title = models.CharField(max_length=100, null=True, blank=True, verbose_name='标题')
    url = models.ImageField(storage=OssStorage('xxxx/mainimage/'), verbose_name='图片')

    class Meta:
        verbose_name = '主图'
        verbose_name_plural = verbose_name

执行makemigrations时抛异常:

Traceback (most recent call last): File "D:\codes\zzc\orderingshop\manage.py", line 22, in main() File "D:\codes\zzc\orderingshop\manage.py", line 18, in main execute_from_command_line(sys.argv) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management__init__.py", line 442, in execute_from_command_line utility.execute() File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management\base.py", line 412, in run_from_argv self.execute(args, cmd_options) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management\base.py", line 458, in execute output = self.handle(args, options) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management\base.py", line 106, in wrapper res = handle_func(*args, kwargs) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management\commands\makemigrations.py", line 259, in handle self.write_migration_files(changes) File "D:\pyvenv\orderingshop\lib\site-packages\django\core\management\commands\makemigrations.py", line 363, in write_migration_files migration_string = writer.as_string() File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\writer.py", line 141, in as_string operation_string, operation_imports = OperationWriter(operation).serialize() File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\writer.py", line 99, in serialize _write(arg_name, arg_value) File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\writer.py", line 63, in _write arg_string, arg_imports = MigrationWriter.serialize(_arg_value) File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\writer.py", line 282, in serialize return serializer_factory(value).serialize() File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\serializer.py", line 226, in serialize return self.serialize_deconstructed(path, args, kwargs) File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\serializer.py", line 91, in serialize_deconstructed arg_string, arg_imports = serializer_factory(arg).serialize() File "D:\pyvenv\orderingshop\lib\site-packages\django\db\migrations\serializer.py", line 391, in serializer_factory raise ValueError( ValueError: Cannot serialize: There are some values Django cannot serialize into migration files. For more, see https://docs.djangoproject.com/en/4.2/topics/migrations/#migration-serializing

解决方法:

在自定义存储类OssStorage中重写方法

    def deconstruct(self):
        # 返回字段名称、路径、位置参数和关键字参数
        path = 'cloudstorage.storage.OssStorage'
        kwargs = {
            'upload_to': self.upload_to,
        }
        return (path, [], kwargs)

文章评论

暂无评论

添加评论





本栏推荐

站点信息

  • 建站时间:2021-01-01
  • 网站程序:Django 3.1.2
  • 文章统计:53篇
  • 文章评论:31条
  • 统计数据