如何使用 json 请求将图像发送到 DRF?
How to send images to DRF with json request?
我在做电商项目,想从前端添加产品。我在 Django 中的产品应用程序中的文件如下
models.py:
from django.db import models
from django.forms import CharField
from PIL import Image
from io import BytesIO
from django.core.files import File
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'/{self.slug}/'
class Product(models.Model):
category = models.ForeignKey(Category, related_name='product', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(decimal_places=6, max_digits=6)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_added',)
def __str__(self):
return self.name
def create_thumbnail(self, image, size = (300,200)):
img = Image.open(image)
img.convert('RGB')
img.thumbnail(size)
thumb_io = BytesIO()
img.save(thumb_io, 'JPEG')
thumbnail = File(thumb_io, name=image.name)
return thumbnail
def get_image(self):
if self.image:
return f'http://localhost:8000' + self.image.url
else:
return ''
def get_thumbnail(self):
if self.thumbnail:
return f'http://localhost:8000' + self.thumbnail.url
else:
if self.image:
self.thumbnail = self.create_thumbnail(self.image)
self.save()
return f'http://localhost:8000' + self.thumbnail.url
else:
return ''
def get_absolute_url(self):
return f'/{self.slug}/'
views.py:
from sys import excepthook
from unicodedata import category
from django.http import Http404
from django.shortcuts import render
from .serializers import ProductSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from rest_framework import status
# Create your views here.
class LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class Productclass LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug = category_slug).get(slug=product_slug)
except Product.DoesNotExits:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug = category_slug).get(slug=product_slug)
except Product.DoesNotExits:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)
serializers.py:
from dataclasses import fields
from pyexpat import model
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [
'id',
'name',
'category',
'get_absolute_url',
'description',
'price',
'get_image',
'get_thumbnail',
]
它在获取数据(我在 Django 管理中创建的产品)时工作正常,但如何发送 JSON 请求也包含图像以及名称、描述等文本数据. 目前,我可以通过发送 POST 请求来创建产品,但无法将图像发送到端点
实际上,你没有。如果要发送文件,最好将其作为 multipart/formdata 而不是 json 发送。
在 DRF 中,这需要您更改视图的默认解析器。
参见:https://www.django-rest-framework.org/api-guide/parsers/#multipartparser
但是,如果您真的需要使用 json 格式,我想您可以将文件转换为 str 表示形式(在前面 - 检查 base64 编码),然后以 json 最后在后面将str表示转化为文件。但是,我不建议您这样做,因为它会使过程更加繁琐
我在做电商项目,想从前端添加产品。我在 Django 中的产品应用程序中的文件如下
models.py:
from django.db import models
from django.forms import CharField
from PIL import Image
from io import BytesIO
from django.core.files import File
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'/{self.slug}/'
class Product(models.Model):
category = models.ForeignKey(Category, related_name='product', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(decimal_places=6, max_digits=6)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_added',)
def __str__(self):
return self.name
def create_thumbnail(self, image, size = (300,200)):
img = Image.open(image)
img.convert('RGB')
img.thumbnail(size)
thumb_io = BytesIO()
img.save(thumb_io, 'JPEG')
thumbnail = File(thumb_io, name=image.name)
return thumbnail
def get_image(self):
if self.image:
return f'http://localhost:8000' + self.image.url
else:
return ''
def get_thumbnail(self):
if self.thumbnail:
return f'http://localhost:8000' + self.thumbnail.url
else:
if self.image:
self.thumbnail = self.create_thumbnail(self.image)
self.save()
return f'http://localhost:8000' + self.thumbnail.url
else:
return ''
def get_absolute_url(self):
return f'/{self.slug}/'
views.py:
from sys import excepthook
from unicodedata import category
from django.http import Http404
from django.shortcuts import render
from .serializers import ProductSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from rest_framework import status
# Create your views here.
class LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class Productclass LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug = category_slug).get(slug=product_slug)
except Product.DoesNotExits:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug = category_slug).get(slug=product_slug)
except Product.DoesNotExits:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)
serializers.py:
from dataclasses import fields
from pyexpat import model
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [
'id',
'name',
'category',
'get_absolute_url',
'description',
'price',
'get_image',
'get_thumbnail',
]
它在获取数据(我在 Django 管理中创建的产品)时工作正常,但如何发送 JSON 请求也包含图像以及名称、描述等文本数据. 目前,我可以通过发送 POST 请求来创建产品,但无法将图像发送到端点
实际上,你没有。如果要发送文件,最好将其作为 multipart/formdata 而不是 json 发送。 在 DRF 中,这需要您更改视图的默认解析器。 参见:https://www.django-rest-framework.org/api-guide/parsers/#multipartparser
但是,如果您真的需要使用 json 格式,我想您可以将文件转换为 str 表示形式(在前面 - 检查 base64 编码),然后以 json 最后在后面将str表示转化为文件。但是,我不建议您这样做,因为它会使过程更加繁琐