【问题标题】:Integrating S3 upload/browsing with django-tinymce将 S3 上传/浏览与 django-tinymce 集成
【发布时间】:2011-12-07 05:06:55
【问题描述】:

我一直在寻找有关如何将 Amazon S3 与 TinyMCE 集成的资源。到目前为止我想出的最佳链接是:http://forums.aurigma.com/yaf_postst4033_Amazon-S3-File-Manager-for-TinyMCE-and-CKEditor.aspx

有没有人有任何将它集成到 Django 应用程序中的经验?如果没有,有哪些替代解决方案可以用于富文本编辑和从 S3 中提取图像?

【问题讨论】:

  • 因此,在与没有 Grappelli 的 django-filebrowser 的维护者交谈后,似乎没有用于 S3 的 Filebrowser 的 StorageBackend。哦,好吧,Django-CMS 已经提供了可以通过 django-storages 推送到 S3 的文件上传,但它确实使编辑有些复杂。

标签: django amazon-s3 tinymce


【解决方案1】:

如果有人最近像我一样搜索过这个并且需要一个解决方案来让 django-tinymce4-lite 与 django-storages 和 django-filebrowser-no-grappelli 一起工作,我已经设法通过执行以下操作使其工作:

1) 关注这个优秀的教程:https://karansthr.gitlab.io/fosstack/how-to-set-up-tinymce-in-django-app/

2) 要使 s3 部分正常工作,您需要安装 django-storages 并按照说明here 中的说明设置您的 mediastorages

3) 您需要创建一个 S3Boto3Storage 的子类,并将其设为您的 DEFAULT_FILE_STORAGE,如下所示:

DEFAULT_FILE_STORAGE = 'path.to.module.MediaStorage'

4) 在该模块中创建 MediaStorage 类,使用以下 API 来使用 FileBrowser

class MediaStorage(S3Boto3Storage):
    location = settings.MEDIAFILES_LOCATION
    isfilecached = {}

    def isdir(self, name):
        if not name:  # Empty name is a directory
            return True

        if self.isfile(name):
            return False

        return True

    def isfile(self, name):
        if len(name.split('.')) > 1:
            return True
        try:
            name = self._normalize_name(self._clean_name(name))
            if self.isfilecached.get(name) is not None:
                return self.isfilecached.get(name)

            f = S3Boto3StorageFile(name, 'rb', self)
            if "directory" in f.obj.content_type:
                isfile = False
            else:
                isfile = True
        except Exception:
            isfile = False
        self.isfilecached[name] = isfile
        return isfile

    def move(self, old_file_name, new_file_name, allow_overwrite=False):

        if self.exists(new_file_name):
            if allow_overwrite:
                self.delete(new_file_name)
            else:
                raise "The destination file '%s' exists and allow_overwrite is False" % new_file_name

        old_key_name = self._encode_name(self._normalize_name(self._clean_name(old_file_name)))
        new_key_name = self._encode_name(self._normalize_name(self._clean_name(new_file_name)))

        k = self.bucket.meta.client.copy(
            {
                'Bucket': self.bucket.name,
                'Key': new_key_name
            },
            self.bucket.name,
            old_key_name
        )

        if not k:
            raise "Couldn't copy '%s' to '%s'" % (old_file_name, new_file_name)

        self.delete(old_file_name)

    def makedirs(self, name):
        name = self._normalize_name(self._clean_name(name))
        return self.bucket.meta.client.put_object(Bucket=self.bucket.name, Key=f'{name}/')

    def rmtree(self, name):
        name = self._normalize_name(self._clean_name(name))
        delete_objects = [{'Key': f"{name}/"}]

        dirlist = self.listdir(self._encode_name(name))
        for item in dirlist:
            for obj in item:
                obj_name = f"{name}/{obj}"
                if self.isdir(obj_name):
                    obj_name = f"{obj_name}/"
                delete_objects.append({'Key': obj_name})
        self.bucket.delete_objects(Delete={'Objects': delete_objects})

    def path(self, name):
        return name

    def listdir(self, name):
        directories, files = super().listdir(name)
        if '.' in files:
            files.remove('.')
        return directories, files

    def exists(self, name):
        if self.isdir(name):
            return True
        else:
            return super().exists(name)

    def get_modified_time(self, name):
        try:
            # S3 boto3 library requires that directorys have the trailing slash
            if self.isdir(name):
                name = f'{name}/'
            modified_date = super().get_modified_time(name)
        except Exception:
            modified_date = timezone.now()
        return modified_date

    def size(self, name):
        try:
            # S3 boto3 library requires that directorys have the trailing slash
            if self.isdir(name):
                name = f'{name}/'
            size = super().size(name)
        except Exception:
            size = 0
        return size

5) 确保将这些放在您的 Django 设置中:

MEDIAFILES_LOCATION = 'media'
DEFAULT_FILE_STORAGE = 'path.to.module.MediaStorage'

FILEBROWSER_DEFAULT_PERMISSIONS = None
FILEBROWSER_LIST_PER_PAGE = 5  # Speeds up the load of the filebrowser files

AWS_PRELOAD_METADATA = True     # Speeds up the load of the filebrowser files
AWS_QUERYSTRING_AUTH = False    # Speeds up the load of the filebrowser files

希望对你有帮助

【讨论】:

  • 这拯救了我的一天!
  • @toose121 有趣的事情我今天正在研究这个并做了一些增强以加快速度,当 S3 文件夹有很多文件时可能需要一段时间,这个新类与 Django设置有助于显着加快速度
  • 谢谢,我试试看!出于好奇,您是否知道我将如何修改上述内容以仅支持私有媒体文件,即无法通过其 s3 url 访问的文件,但仅限于我的应用程序的经过身份验证的用户?我以this 为指导,但链接似乎已过期。你将如何解决这个问题?
  • 我自己没有尝试过,但现在我有兴趣尝试,this 链接有帮助吗?也许通过引用的域限制对存储桶的访问可能是一种选择
  • 这实际上是我的选择。很高兴看到验证,因为您也发布了相同的解决方案。唯一让我感到厌烦的是,我的存储桶显示了一个红色星号,表明它是公开的。也就是说,该政策适用于我的推荐人政策设置为“来源”。干杯!
【解决方案2】:

我最终使用了django-storages。完美运行。

【讨论】:

  • 您是如何让一切正常运行的?您最终是否为它创建了自己的 GUI 前端?
  • 其实都是透明的。当我通过 Django-CMS 上传图像时,它们提供了“图像”内容插件的表单。从那里它直接进入 MEDIA_URL 指定的存储桶。
  • 我注意到文件插件不适用于 s3 后端。
  • 我没试过文件插件,但是图片对我有用。
  • 令人失望的是这是公认的答案。正如其他人所提到的,该用户没有对其进行测试,或者它在未来的某个时候发生故障并且不再相关。似乎当前的 django-tinymce 包有一个错误的 URL 生成器,因为它通过 S3 创建的 JS URL 在我的测试中被破坏了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2011-04-30
  • 1970-01-01
  • 2012-06-07
  • 2023-03-28
相关资源
最近更新 更多