如何通过django rest框架在一个目录中发布多个图片

oxf4rvwz  于 2022-12-01  发布在  Go
关注(0)|答案(1)|浏览(96)

我尝试使用django rest框架来执行多个POST事件,只要我将它指向一个目录。我的想法是,我将指定国家和一个包含多个图像的目录。然后API必须转到目录,并将该目录中的每个图像以及每个图像的文件名中的更多详细信息发布到数据库中。遵循互联网上的一些指针,我设法构建了一个小模型和框架,看起来它可以工作,除了一件事。默认的休息API页面不支持列表的HTML输入。
我想知道我的时间是否会更好地花在尝试使API页面符合我的要求上,或者我是否应该着手构建我自己的HTML界面。
或者说得更直接些
使用Django和Django REST框架上传多个图像(每个图像在数据库中是一个独立的示例)到数据库中最快(也是最简单)的方法是什么?

型号.py:

from django.db import models

# Create your models here.
class Tiles(models.Model):
    image = models.ImageField(blank=True, null=True)
    lat = models.FloatField(blank=True, null=True)
    lng = models.FloatField(blank=True, null=True)
    country = models.CharField(blank=True, null=True, max_length=10)
    solar = models.FloatField(blank=True, null=True)
    wind = models.FloatField(blank=True, null=True)
    HV = models.FloatField(blank=True, null=True)

    class Meta:
        verbose_name_plural = "Tiles"

查看次数.py

from django.shortcuts import render
from rest_framework import viewsets
from .serializers import FileListSerializer
from rest_framework import parsers
from .models import Tiles

# Create your views here.
def index(request):
    return render(request, 'main/index.html')

class TileViewSet(viewsets.ModelViewSet):
    serializer_class = FileListSerializer
    parser_classes = (parsers.MultiPartParser, parsers.FormParser,)
    queryset = Tiles.objects.all()

序列化程序.py

from rest_framework import serializers
from .models import Tiles
import mercantile

class FileListSerializer(serializers.Serializer):
    image = serializers.ListField(
                       child=serializers.FileField(max_length=100000,
                                         allow_empty_file=False,
                                         use_url=False)
                                )
    country = serializers.CharField(max_length=10)

    # The create function below overrides the Django default create function to populate multiple fields using the image name

    def create(self, validated_data):

        country = validated_data.pop('country')
        image = validated_data.pop('image')
        for img in image:

            path = img.path
            path = path.split('/')[-1]
            path = path.split('.')[0]
            x, y, z = path.split('-')
            coords = mercantile.ul(int(x), int(y), int(z))

            tile = Tiles.objects.create(image=img, country=country, lat=coords.lat, lng=coords.lng, **validated_data)

        return tile

class TileSerializer(serializers.ModelSerializer):

    class Meta:
        model = Tiles
        fields = '__all__'

生成的API页面的屏幕截图:

lhcgjxsq

lhcgjxsq1#

我找到了一个解决这个问题的方法。希望这能对下面的人有所帮助。在www.example.com中serializers.py我将ListField更改为FilePathField,它可以将目录作为输入。
新网站serializers.py:

from rest_framework import serializers
from .models import Tiles
import mercantile
import os

BASE_DIR = os.path.dirname((os.path.dirname(os.path.abspath(__file__))))

class FileListSerializer(serializers.Serializer):

    # The following FilePathField is named image but refers to a directory containing multiple images
    image = serializers.FilePathField(path=(os.path.join(BASE_DIR, 'opt_rec_master_img_dir')), allow_files=False, allow_folders=True)
    country = serializers.CharField(max_length=10)

    # The following variables for each instance are generated automatically upon clicking create
    # They are included here so that the DRF auto generated json output includes this information
    lat = serializers.FloatField(read_only=True)
    lng = serializers.FloatField(read_only=True)
    solar = serializers.FloatField(read_only=True)
    wind = serializers.FloatField(read_only=True)
    HV = serializers.FloatField(read_only=True)

    # This function overrides the default create function to populate multiple fields given a directory full of images.
    def create(self, validated_data):

        country = validated_data.pop('country')
        image = validated_data.pop('image')

        directory = image.split('/')[-1]
        for img in os.listdir(image):
            path = img.split('.')[0]
            x, y, z = path.split('-')
            coords = mercantile.ul(int(x), int(y), int(z))
            tile = Tiles.objects.create(image=os.path.join('opt_rec_master_img_dir', directory, img), country=country, lat=coords.lat, lng=coords.lng)

        return tile

    class Meta:
        model = Tiles

views.py

from django.shortcuts import render
from rest_framework import viewsets
from .serializers import FileListSerializer
from .models import Tiles
from django.core.files.images import ImageFile
from rest_framework.utils.encoders import JSONEncoder
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer

# Create your views here.
# def index(request):
#     return render(request, 'main/index.html')
#

# JSONEncoder and JSONRenderer have been overriden here to serialize the image path rather than image byte data
class OREncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, ImageFile):
            return obj.path

        return super().default(obj)

class ORRenderer(JSONRenderer):
    encoder_class = OREncoder

class TileViewSet(viewsets.ModelViewSet):
    serializer_class = FileListSerializer
    queryset = Tiles.objects.all()
    renderer_classes = [ORRenderer, BrowsableAPIRenderer]

相关问题