Django Rest Framework (DRF) - Загрузка файлов
В этой статье рассмотрим как можно загружать файлы с помощью Django Rest Framework.
Рассмотрим простой случай. У нас есть модель Post , у которого есть поле preview , куда нужно загружать изображения
Файл blog/models.py
from django.db import models
class Post(models.Model):
name = models.CharField(max_length=255)
preview = models.ImageField(upload_to='posts')
content = models.TextField()
def __str__(self):
return self.name
class Meta:
verbose_name = 'Пост'
verbose_name_plural = 'Посты'
Создаем сериализатор blog/serializers.py
from rest_framework.serializers import ModelSerializer
from blog.models import Post
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ('name', 'preview', 'content')
Создаем стандартный modelvewset blog/views.py
from rest_framework import viewsets
from blog.models import Post
from blog.serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
Создаем blog/urls.py
from django.urls import include, path
from rest_framework.routers import SimpleRouter
from blog.views import PostViewSet
router = SimpleRouter()
router.register(r'posts', PostViewSet, basename='posts')
urlpatterns = [
path('', include(router.urls)),
]
И в вашем основном файле urls.py добавьте следующие строки.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/blog/', include(('blog.urls', 'blog'), namespace='blog')),
]
Попробуем через стандартную интерфейс создать новый пост.
При запросе используется значение Content-Type равной 'multipart/form-data'.
С помощью curl запрос на добавление нового поста делается следующим образом
curl -X POST -F "name=Второй запрос" -F "content=текст второго поста" -F preview=@dune.png http://localhost:8000/api/blog/posts/
Пост создался и файл загрузился. Магия. Все работает и мы даже не знаем как. Давайте попытаемся разобраться.
Когда обрабатывается запрос , то при доступе к request.data DRF проверит заголовок Content-Type во входящем запросе и определит, какой синтаксический анализатор(Парсер) использовать для анализа содержимого запроса. Так как в нашем случае при отправке файлов Content-Type равно multipart/form-data , то DRF для парсинга входящих данных будет использовать парсер MultiPartParser. Это происходит отчасти и из-за того , что данный парсер по умолчанию указан в DRF
По умолчанию DRF определяет следующие парсеры:
DEFAULTS = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
Также MultiPartParser использует обработчики для сохранения отправленных файлов(По умолчанию , используются стандартные загрузчики файлов Django)