【问题标题】:Absolute paths on images uploaded by django-ckeditordjango-ckeditor 上传的图片的绝对路径
【发布时间】:2020-08-03 02:32:18
【问题描述】:

我将django-rest-frameworkdjango-ckeditor 结合使用。我正在使用绝对 url-s 提供一些图像,没有任何问题。但是ckeditor上传的图片和文件是作为相对路径的,因为在不同的域中,所以不能在客户端显示。

这是我得到的一个例子:

{
    image: "http://example.com/media/myimage.png",
    body: "<p><a href=\"/media/ckeditor/myfile.pdf\">download my file</a></p>"
}

这就是我想要得到的:

{
    image: "http://example.com/media/myimage.png",
    body: "<p><a href="http://example.com/media/ckeditor/myfile.pdf\">download my file</a></p>"
}

编辑: 这将是我的示例模型:

from django.db import models
from ckeditor_uploader.fields import RichTextUploadingField

image: models.ImageField()
body: RichTextUploadingField(blank=True,null=True)

【问题讨论】:

    标签: django django-rest-framework django-ckeditor


    【解决方案1】:

    我会使用自定义序列化程序来解决这个问题:

    from rest_framework import serializers
    
    
    def relative_to_absolute(url):
        return 'http://127.0.0.1:8000' + url
    
    
    class FileFieldSerializer(serializers.Field):
        def to_representation(self, value):
            url = value.url
            if url and url.startswith('/'):
                url = relative_to_absolute(url)
            return url
    

    当 filefield.url 包含相对 url 时,调用 relative_to_absolute() 来添加域。

    这里我只是使用了一个常量字符串;您可以将其保存在您的设置中,或者,如果安装了 Django Site 框架,则按如下方式检索它:

    from django.contrib.sites.models import Site
    
    domain=Site.objects.get_current().domain
    

    自定义序列化程序的示例用法:

    class Picture(BaseModel):
        ...
        image = models.ImageField(_('Image'), null=True, blank=True)
        ...
    
    
    class PictureSerializer(serializers.ModelSerializer):
        image = FileFieldSerializer()
        class Meta:
            model = Picture
            fields = '__all__'
    

    RichTextUploadingField 的变体

    另一方面,如果您使用的是 CKEditor 的 RichTextUploadingField,那么您的字段基本上就是一个 TextField,其中 HTML 片段保存在图像上 上传。

    在这个 HTML 片段中,CKEditor 将使用相对路径引用上传的图像,原因很充分:

    • 如果更改域,您的网站仍然可以运行
    • 开发实例将在 localhost 中运行
    • 毕竟,我们使用的是 Django,而不是 WordPress ;)

    所以,我不会碰它,而是在运行时在自定义序列化程序中修复路径:

    SEARCH_PATTERN = 'href=\\"/media/ckeditor/'
    SITE_DOMAIN = "http://127.0.0.1:8000"
    REPLACE_WITH = 'href=\\"%s/media/ckeditor/' % SITE_DOMAIN
    
    class FixAbsolutePathSerializer(serializers.Field):
    
        def to_representation(self, value):
            text = value.replace(SEARCH_PATTERN, REPLACE_WITH)
            return text
    

    或者,域可以保存在设置中:

    from django.conf import settings
    
    REPLACE_WITH = 'href=\\"%s/media/ckeditor/' % settings.SITE_DOMAIN
    

    或从 Django Site 框架中检索如下:

    from django.contrib.sites.models import Site
    REPLACE_WITH = 'href=\\"{scheme}{domain}/media/ckeditor/'.format(
        scheme="http://",
        domain=Site.objects.get_current().domain
    )
    

    您可能需要根据您的 CKEditor 配置调整SEARCH_PATTERN;越具体越好。

    示例用法:

    class Picture(BaseModel):
        ...
        body = RichTextUploadingField(blank=True,null=True)
        ...
    
    
    class PictureSerializer(serializers.ModelSerializer):
        body = FixAbsolutePathSerializer()
        class Meta:
            model = Picture
            fields = '__all__'
    

    【讨论】:

    • 谢谢马里奥的回答!问题是我的文件是CKEditorRichTextUploadingField,它不是'FileField'。上传的文件路径混杂了更多的文字
    • 您能否提供一个上传后 RichTextUploadingField 实例的示例?它是嵌入了一些 标签的 HTML 文本吗?
    • 我的问题中有一个例子。它是一个带有href 标签的 HTML 文本
    • 啊,现在我明白了:在您的模型中,您有一个名为“image”的 ImageField 和一个名为“body”的 RichTextUploadingField 字段;后者是一个文本字段,其中包含 django-ckeditor 在上传时提供的 HTML 片段。我认为我建议的 sn-p 的一个简单变体可以解决它:一个自定义序列化程序,其中将解析 'body' 文本字段以将任何出现的 'example.com/media/ckeditor'。我不会触及您模型的内容,因为附件的相对 url 在这种情况下非常合适。
    • @cor,我更新了我的答案以包含 RichTextUploadingField 用例。我从未使用过它,而是使用纯 TextField 进行了快速测试。您可能需要稍微调整 SITE_DOMAIN。 Br
    猜你喜欢
    • 1970-01-01
    • 2017-07-27
    • 2019-07-16
    • 2020-06-07
    • 2013-06-05
    • 1970-01-01
    • 2020-10-13
    • 2021-07-28
    • 1970-01-01
    相关资源
    最近更新 更多