django保存图片并返回url

场景描述

前端传递一个表单,表单中有title,description,以及image等信息,image在这里传递的是二进制文件
后端需要将这些数据保存到一个数据库中。image需要保存到指定文件夹下,并且数据库中保存的是image的路径,
之后我们可以通过浏览器访问 类似 127.0.0.1:8000/xxx/a.jpg 访问到这张图片

步骤

这个问题忙活了很久,网上的说法众说纷纭,借助于ChatGpt才将问题得以解决,我的django版本是4.2

  1. 配置MEDIA的相关信息
    我这里的配置如下:image
    这里的MEDIA_URL就是我们访问时127.0.0.1:8000后面的地址
    这里的MEDIA_ROOT则是图片保存的文件夹
  2. 编写对应的模型,也就是是models.py文件
class ImgSave(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField()
    imgURL = models.ImageField(upload_to='notices')
  1. 编写对应的视图函数,用户前端提交表单信息。我们要做的就是将图片保存到刚才配置的MEDIA_ROOT文件夹下,并在数据库中存入对应地址。存入的时候我们使用的是FileSystemStorage,Django自带的媒体文件存储类
# 注意自己引入对应的模型以及方法
from .models import ImgSave
from django.conf import settings
from django.core.files.storage import FileSystemStorage
import os
class SaveImg(View):
    def post(self, request):
        # media下面的文件夹名字,可以不写,不写就默认是在media文件夹下
	# 1. 获取post方法传递过来的数据
        file_name = 'notices/'
        title = request.POST.get('title')
        description = request.POST.get('description')
        image = request.FILES.get('image')
        # print(title, description, type(image))
	# 2. 将图片进行保存,可以用with open的方法进行保存,在django中我们直接自带的FIleSystemStorage
        fs = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT,file_name))
        img_name = fs.save(image.name, image)
	# 3. 对url进行处理,保存成我们浏览器可以直接访问的格式
        #  /ip:port + /media/ + /notices/ + a.png
        img_url = '127.0.0.1:8000'+settings.MEDIA_URL+file_name+img_name
        try:
	# 4. 将相关信息保存到数据库
            ImgSave.objects.create(title=title, description=description, imgURL=img_url)
            return JsonResponse({'status':'success','url':img_url},status=200)
        except Exception as e:
            return JsonResponse({'status': 'error', "msg": e}, status=400)

  1. 配置表单提交的接口,这里的知识点不再描述。我使用的是面向对象的方式写的视图,所以写法上跟函数式可能有差别,我的二级路由配置如下:
    image
    仅作参考
  2. 在根路由中配置
    在urlpatterns的数组后面添加上 static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    列出我项目根路由的信息
    image
    相关代码
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
    path('admin/', include('BackstageApi.urls')),
    path('test/', include('Testing.urls')),
    path('', include('ForegroundApi.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

结果展示

之后前端通过提交表单的方式将数据进行提交,我们就可以通过返回的url_img数据进行图片的访问
image

image
我这里是因为测试的时候该图片已经上传过一次了,也就是存在同名文件,django后台自动做的处理

前端示例代码

仅供参考

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Registration Form</title>

    <!-- Import Vue.js from CDN -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- Import Bootstrap CSS from CDN -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css">
    <!-- Import axios from CDN -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

</head>


<body>
    <div id="app" class="container">
        <h1>Registration Form</h1>
        <form>
            <div class="mb-3">
                <label for="title" class="form-label">Title</label>
                <input type="text" class="form-control" id="title" v-model="title">
            </div>
            <div class="mb-3">
                <label for="description" class="form-label">Description</label>
                <input type="text" class="form-control" id="description" v-model="description">
            </div>
            <div class="mb-3">
                <label for="image" class="form-label">Image</label>
                <input type="file" class="form-control" id="image" v-on:change="onFileChange">
            </div>
          
            <button type="submit" class="btn btn-primary" v-on:click.prevent="submitForm">Submit</button>
        </form>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                title: '好吃的不得了',
                description: '发射点发射点发射点发法大师傅大师傅撒范德萨',
                image: ''
            },
            methods: {
                onFileChange(e) {
                    this.image = e.target.files[0];
                },
                submitForm() {
                    // Handle form submission here
                    console.log(this.title, this.description, this.image)
                    let formData = new FormData();
                    formData.append('title', this.title);
                    formData.append('description', this.description);
                    formData.append('image', this.image);
                    axios.post('http://localhost:8000/test/upload', formData, {
                        headers: {
                            'Content-Type': 'multipart/form-data'
                        }
                    })
                        .then(function (response) {
                            console.log(response);
                        })
                        .catch(function (error) {
                            console.log(error);
                        });
                }
            }
        });
    </script>

   
    </script>
</body>

</html>

注意事项

  1. 在model.py中需要使用ImageField时,需要手动安装 pip install Pillow
    Pillow的主要功能是对图片进行处理,保存的是一个对象,可以对图片类型,大小等进行处理。
    存储的ImageField并不是一个字符串,是一个对象
from django.db import models
class MyModel(models.Model):
    imgURL = models.ImageField(upload_to='notices')
my_model = MyModel.objects.first()
img_url = my_model.imgURL.url  # 获取图片的 URL 地址
img_width = my_model.imgURL.width  # 获取图片的宽度
img_height = my_model.imgURL.height  # 获取图片的高度

如果我们不需要对图片进行处理,我们使用URLField完全足够。

posted @ 2023-04-16 20:22  含若飞  阅读(453)  评论(0编辑  收藏  举报