我将其指向目录后,尝试使用django rest框架执行多个POST事件。我的想法是,我将指定国家和一个包含多张图片的目录。然后,API必须转到该目录,并将该目录中的每个图像以及每个图像的文件名中可用的更多详细信息发布到数据库。遵循互联网上的一些指示,我设法建立了一个看起来可以运行的小模型和框架,除了一件事之外。默认的rest API页面不支持列表的HTML输入。

我想知道我的时间是否可以花在尝试使API页面适合我的需求上,还是应该建立自己的HTML接口。

或者更直接

对我来说,使用Django和Django REST Framework将多个图像(每个图像是数据库中的一个单独实例)上载到数据库的最快(最简单)方式是什么?

models.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"



views.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()


serializers.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页面的屏幕截图:
python - 如何通过django rest框架一键发布目录中的多个图像-LMLPHP

最佳答案

我找到了解决这个问题的方法。希望这可以帮助某人。在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]

关于python - 如何通过django rest框架一键发布目录中的多个图像,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57759826/

10-14 19:50
查看更多