Django将多个图片保存成一个URL串返回给前端

说明

Django有ImageField字段,是封装好的,使用很方便,但是一个ImageField字段只能保存一张图片的URL,我现在是想将多张图片保存在一个字段里,然后URL和URL之间用一个自定义的分隔符连接起来,这样不用为了图片再设计一个字表。

自定义上传图片

设置settings.py文件,添加如下语句

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
IMAGE_ROOT = os.path.join(MEDIA_ROOT, 'images/')
WEB_HOST_MEDIA_URL = os.path.join('http://127.0.0.1:8000', MEDIA_URL[1:], 'images/')

MEDIA_ROOT代表的是用户上传后的文件一般保存的地方,一般在放在项目目录下,例如BASE_DIR就是取得项目绝对地址。而MEDIA_URL是指URL访问时的URL。例如,
BASE_DIR: /Users/incisor/VSCodeProjects/python/Notes,
那么
MEDIA_ROOT:/Users/incisor/VSCodeProjects/python/Notes/media,
假设media目录下有一张图片2019.jpg,那么
MEDIA_URL: http://127.0.0.1:8000/media/
然后再通过http://127.0.0.1:8000/media/2019.jpg这个URL是可以直接访问这个图片的。

IMAGE_ROOT是我自定义的一个字段,因为我想以后可能会上传视频,或者其他一些文件,想区分开,所以我在media目录下再建了一个目录images,那么
IMAGE_ROOT: /Users/incisor/VSCodeProjects/python/Notes/media/images

WEB_HOST_MEDIA_URL是拼接URL时使用,因为我接下来要自己拼接多个图的URL,MEDIA_URL[1:]的原因时如果不去掉第一个/,那WEB_HOST_MEDIA_URL会是/media/images/,这显然不是我们想要的,所以需要把第一个/去掉。

views.py文件

前端传过来不定数量的图片,可能0张,最多9张,每个图片都做base64编码再传过来,POST请求里有个参数imgs,是一个数组,保存base64编码。

base64编码如下图所示,这只是一部分:

前面的data:image/png;base64, 除了后缀会不同,其他的是固定的,所以我会先从这里取得后缀png,再做编码转换。

import base64
import os
import re
from datetime import date, datetime
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

from Notes.settings import IMAGE_ROOT, WEB_HOST_MEDIA_URL


@api_view(['POST',])
def images(request):
    urls = ''
    dir_name = date.today().__str__().replace('-', '_', 2)  # 2019_06_21
    dirs = os.path.join(IMAGE_ROOT, dir_name)  # 将日期作为目录名
    if not os.path.isdir(dirs):
        os.makedirs(dirs)  # 判断目录是否存在,不存在则创建
    for img in request.data['imgs']:
        strs = img.split(',')
        suffix = re.findall(r'/(\w+?);', strs[0])[0]  # 取得文件后缀
        # 拼接服务器上的文件名
        # datetime.now()取得当前时间,精确到了微秒,一般来说是唯一的了,因为目录是日期,所以文件名就去掉日期,最后会是一串数字
        img_name = re.sub(r':|\.', '', datetime.now().__str__().split(' ')[1]) + '.' + suffix  
        img_path = os.path.join(dirs, img_name)
        with open(img_path, 'wb') as out:
            out.write(base64.b64decode(strs[1]))  # base64解码,再写入文件
            out.flush()
            urls += os.path.join(WEB_HOST_MEDIA_URL, dir_name, img_name) + '[/--sp--/]'  # 拼接URL,URL与URL之间用[/--sp--/]隔开
    result = {}
    result['status'] = status.HTTP_200_OK
    result['message'] = '图片上传成功'
    result['urls'] = urls[:len(urls) - len('[/--sp--/]')]  # 去掉末尾的[/--sp--/]
    return Response(data=result)

3、urls.py文件

from django.contrib import admin
from django.urls import path
from django.conf.urls.static import static  # 需要添加这句,包含静态资源之类的
from note import views
from . import settings


urlpatterns = [
    path('notes/images/', views.images),
    path('admin/', admin.site.urls),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # 这句不设置的话,不能通过URL直接访问到图片

4、启动服务,python3 manage.py runserver

5、POST请求,然后返回对应的JSON数据

{
    "status": 200,
    "message": "图片上传成功",
    "urls": "http://127.0.0.1:8000/media/images/2019_06_21/073249204253.png[/--sp--/]http://127.0.0.1:8000/media/images/2019_06_21/073249854323.png"
}

这样在数据库方面,就可以直接用一个varchar类型来存储多张图了,前端收到URL串,再按照定好的分隔符[/–sp–/]切开后,就可以显示了。

你可能感兴趣的:(Django,Django)