【Django DRF Apps】从零搭建一个上传图片app

Django REST Framework 图片上传app完整指南

以下是一个通过 Django REST Framework (DRF) 实现图片上传功能的完整示例,涵盖从环境配置到功能实现的所有步骤,同时增加了功能点和知识点的解析,便于理解与扩展。


功能点

  1. 图片上传功能:实现通过 API 接口上传图片并保存到服务器。
  2. 文件大小与类型验证:限制上传的图片大小和文件类型。
  3. 图片存储路径设置:将图片保存到自定义路径,并支持本地存储与云存储扩展。
  4. 图片访问功能:提供图片的公开访问 URL。
  5. 分页功能:支持图片数据的分页展示,适合大数据量场景。
  6. 权限控制:为上传和访问接口添加用户权限验证。
  7. 图片优化:对上传图片进行压缩和尺寸调整以节省存储空间。
  8. 扩展与生产支持:支持在本地开发和生产环境下的配置切换。

知识点

  1. DRF 基础ModelViewSet 的使用,结合序列化器与模型完成 CRUD。
  2. 图片上传解析器MultiPartParserFormParser 的作用与用法。
  3. Django 文件存储系统MEDIA_URLMEDIA_ROOT 的配置。
  4. 数据验证:如何在序列化器中添加自定义验证逻辑。
  5. 分页设置:自定义分页类实现分页功能。
  6. 信号机制:使用 Django 的信号 (post_save) 实现图片处理。
  7. 安全性优化:限制文件大小和文件类型,防止恶意上传。

完整实现步骤

1. 安装依赖

在项目开始前,确保安装以下依赖库:

pip install django djangorestframework pillow
  • Django:Web 框架。
  • Django REST Framework (DRF):用于构建 API 的工具集。
  • Pillow:Python 图像处理库,用于图片验证和处理。

2. 配置 Django 项目
  1. 创建 Django 项目与应用

    django-admin startproject myproject
    cd myproject
    python manage.py startapp myapp
    
  2. 配置 settings.py

    • 添加 INSTALLED_APPS

      INSTALLED_APPS = [
          ...
          'rest_framework',
          'myapp',
      ]
      
    • 配置媒体文件路径:

      import os
      
      MEDIA_URL = '/media/'
      MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
      
  3. 配置 urls.py
    在项目的 myproject/urls.py 中添加媒体文件支持:

    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        ...
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

3. 创建模型

myapp/models.py 中创建用于存储图片的模型:

from django.db import models

class ImageUpload(models.Model):
    image = models.ImageField(upload_to='images/')  # 指定存储路径
    uploaded_at = models.DateTimeField(auto_now_add=True)  # 自动记录上传时间

    def __str__(self):
        return self.image.name

功能点:

  • upload_to='images/':指定图片上传的目录为 media/images/
  • uploaded_at:记录图片的上传时间。

4. 创建序列化器

myapp/serializers.py 中创建一个序列化器:

from rest_framework import serializers
from .models import ImageUpload

class ImageUploadSerializer(serializers.ModelSerializer):
    class Meta:
        model = ImageUpload
        fields = ['id', 'image', 'uploaded_at']

    def validate_image(self, value):
        # 验证文件类型
        if not value.content_type.startswith('image/'):
            raise serializers.ValidationError('Uploaded file is not a valid image.')
        # 验证文件大小
        if value.size > 5 * 1024 * 1024:  # 限制大小为5MB
            raise serializers.ValidationError('Image size should not exceed 5MB.')
        return value

知识点:

  • validate_<field_name> 方法用于对字段值进行自定义验证。
  • 可以通过 content_type 验证文件类型,通过 size 限制文件大小。

5. 创建视图

myapp/views.py 中创建图片上传接口的视图:

from rest_framework import viewsets
from rest_framework.parsers import MultiPartParser, FormParser
from .models import ImageUpload
from .serializers import ImageUploadSerializer

class ImageUploadViewSet(viewsets.ModelViewSet):
    queryset = ImageUpload.objects.all().order_by('-uploaded_at')  # 按上传时间倒序
    serializer_class = ImageUploadSerializer
    parser_classes = (MultiPartParser, FormParser)  # 处理文件上传的解析器

知识点:

  • MultiPartParserFormParser:处理多部分表单数据,适用于文件上传。
  • ModelViewSet:提供标准的 CRUD 操作,减少代码量。

6. 配置 URL

myapp/urls.py 中注册路由:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ImageUploadViewSet

router = DefaultRouter()
router.register(r'images', ImageUploadViewSet)  # 注册路由

urlpatterns = [
    path('', include(router.urls)),
]

7. 数据库迁移

运行以下命令创建和迁移数据库:

python manage.py makemigrations
python manage.py migrate

8. 运行开发服务器

启动开发服务器进行测试:

python manage.py runserver

9. 测试图片上传
  1. 使用 cURL 测试

    curl -X POST http://127.0.0.1:8000/api/images/ -F "image=@/path/to/image.jpg"
    
  2. 使用 Postman 测试

    • 设置请求方法为 POST
    • URL 为 http://127.0.0.1:8000/api/images/
    • 在表单数据中添加 image 字段并上传图片。

10. 访问上传的图片

上传成功后,可以通过以下 URL 访问图片:

http://127.0.0.1:8000/media/images/<image-name>

附加优化

  1. 分页设置
    settings.py 中全局配置分页:

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 10,  # 每页显示 10 条记录
    }
    
  2. 图片处理
    对上传图片进行压缩或缩放:

    from PIL import Image
    
    def resize_image(image, max_width=800, max_height=800):
        with Image.open(image) as img:
            img.thumbnail((max_width, max_height))
            img.save(image.path, optimize=True, quality=85)
    

    在模型保存后调用:

    from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    @receiver(post_save, sender=ImageUpload)
    def process_image(sender, instance, **kwargs):
        resize_image(instance.image)
    
  3. 权限控制
    限制接口访问权限:

    from rest_framework.permissions import IsAuthenticated
    
    class ImageUploadViewSet(viewsets.ModelViewSet):
        permission_classes = [IsAuthenticated]
    

通过以上步骤,你将实现一个功能完整且安全的图片上传 API,同时具备高可扩展性,支持未来在生产环境中的部署与优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值