Django文件上传后,返回带域名URL地址的代码

Django默认上传文件是不返回带域名的URL地址,但是很多前后端分离开发的项目需要提供上传文件的完整域名地址才能正常显示。以下以图片上传为例:

一、Django默认ImageField上传图片

Django上传图片时并不是直接存储图片,而是存储图片的唯一标识,再通过标识去获取图片,Django中上传图片的字段类型是ImageField。

1.写一个上传图片的models

class SKUImage(BaseModel):    sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')    image = models.ImageField(verbose_name='图片')  # 存储图片
    class Meta:        db_table = 'tb_sku_image'
    def __str__(self):        return '%s %s' % (self.sku.name, self.id)

ImageField类型有一个url属性,返回图片的URL链接,即图片标识。如果想要一个带域名完整的URL地址,需要自定义存储后端,并改写url()函数返回完整图片地址

2.自定义存储后端

新建utils.py,新建一个类让其继承Storage,并重写url()方法,把该方法的name参数拼接上自定义的域名地址再返回

from django.core.files.storage import Storage
class UrlStorage(Storage):    def _open(self,name,mode='rb'):        # 打开django本地文件        pass    def _save(self,name,content,max_length=None):        # 上传图片        pass    # 给返回的图片标识加上前缀    def url(self, name):        return "http://image.mysite.site:8888/" + name

3.修改setting.py配置文件,增加如下设置,告诉Django要使用自定义的存储后端

# 指定自定义的Django文件存储类DEFAULT_FILE_STORAGE = 'utils.UrlStorage' 

上述就可以实现Django默认图片上传返回带域名的url地址

二、ckeditor-uploader上传图片

找到ckeditor-uploer安装路径修改views.py文件,即../site-packages/ckeditor-uploader/views.py
然后找到下面这段代码:

class ImageUploadView(generic.View):    http_method_names = ["post"]
    def post(self, request, **kwargs):        """        Uploads a file and send back its URL to CKEditor.        """        uploaded_file = request.FILES["upload"]
        backend = get_backend()
        ck_func_num = request.GET.get("CKEditorFuncNum")        if ck_func_num:            ck_func_num = escape(ck_func_num)
        filewrapper = backend(storage, uploaded_file)        allow_nonimages = getattr(settings, "CKEDITOR_ALLOW_NONIMAGE_FILES", True)        # Throws an error when an non-image file are uploaded.        if not filewrapper.is_image and not allow_nonimages:            return HttpResponse(                """                <script type='text/javascript'>                window.parent.CKEDITOR.tools.callFunction({}, '', 'Invalid file type.');                </script>""".format(                    ck_func_num                )            )
        filepath = get_upload_filename(uploaded_file.name, request)
        saved_path = filewrapper.save_as(filepath)
        url = utils.get_media_url(saved_path)
        if ck_func_num:            # Respond with Javascript sending ckeditor upload url.            return HttpResponse(                """            <script type='text/javascript'>                window.parent.CKEDITOR.tools.callFunction({}, '{}');            </script>""".format(                    ck_func_num, url                )            )        else:            _, filename = os.path.split(saved_path)            retdata = {"url": url, "uploaded": "1", "fileName": filename}            return JsonResponse(retdata)
......
def get_files_browse_urls(user=None):    """    Recursively walks all dirs under upload dir and generates a list of    thumbnail and full image URL's for each file found.    """    files = []    for filename in get_image_files(user=user):        src = utils.get_media_url(filename)        if getattr(settings, "CKEDITOR_IMAGE_BACKEND", None):            if is_valid_image_extension(src):                thumb = utils.get_media_url(utils.get_thumb_filename(filename))            else:                thumb = utils.get_icon_filename(filename)            visible_filename = os.path.split(filename)[1]            if len(visible_filename) > 20:                visible_filename = visible_filename[0:19] + "..."        else:            thumb = src            visible_filename = os.path.split(filename)[1]        files.append(            {                "thumb": thumb,                "src": src,                "is_image": is_valid_image_extension(src),                "visible_filename": visible_filename,            }        )
    return files

将代码中的url、src进行修改,添加域名或服务器地址,拼接带域名的返回值地址。

url = utils.get_media_url(saved_path)替换成url = 'http://127.0.0.1:8000'+ utils.get_media_url(saved_path)src = utils.get_media_url(filename)替换成src = 'http://127.0.0.1:8000'+ utils.get_media_url(filename)

然后就成功实现。

图片

THE END