django-ckeditor 上传图片的绝对路径

cor*_*cor 5 django django-rest-framework django-ckeditor

我正在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>"
}
Run Code Online (Sandbox Code Playgroud)

这就是我想要得到的:

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

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

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

image: models.ImageField()
body: RichTextUploadingField(blank=True,null=True)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ndi 5

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

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
Run Code Online (Sandbox Code Playgroud)

当 filefield.url 包含一个相对 url 时,relative_to_absolute()被调用以预先添加域。

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

from django.contrib.sites.models import Site

domain=Site.objects.get_current().domain
Run Code Online (Sandbox Code Playgroud)

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

class Picture(BaseModel):
    ...
    image = models.ImageField(_('Image'), null=True, blank=True)
    ...


class PictureSerializer(serializers.ModelSerializer):
    image = FileFieldSerializer()
    class Meta:
        model = Picture
        fields = '__all__'
Run Code Online (Sandbox Code Playgroud)

RichTextUploadingField 的变化

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

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

  • 如果域更改,您的站点仍然可以工作
  • 开发实例将在本地主机中工作
  • 毕竟,我们使用的是 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
Run Code Online (Sandbox Code Playgroud)

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

from django.conf import settings

REPLACE_WITH = 'href=\\"%s/media/ckeditor/' % settings.SITE_DOMAIN
Run Code Online (Sandbox Code Playgroud)

或从 Django 站点框架检索如下:

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

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

示例用法:

class Picture(BaseModel):
    ...
    body = RichTextUploadingField(blank=True,null=True)
    ...


class PictureSerializer(serializers.ModelSerializer):
    body = FixAbsolutePathSerializer()
    class Meta:
        model = Picture
        fields = '__all__'
Run Code Online (Sandbox Code Playgroud)