python - 如何通过django Rest框架一键发布目录中的多张图片

标签 python django django-rest-framework

一旦我将 django 休息框架指向一个目录,我就会尝试使用它来执行多个 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()

序列化器.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 页面的屏幕截图: Django rest framework autogenerated API page

最佳答案

我已经找到了解决这个问题的方法。希望这可以帮助某人。在serializers.py中,我将ListField更改为FilePathField,它可以将目录作为输入。

新的序列化器.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

View .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/

相关文章:

Django Rest 框架 imagefield 可选

django - 如何使用 Simple JWT (django rest) 将 JWT token 列入黑名单?

django.request : Forbidden (Referer checking failed - no Referer. )

django - 如何使用查询参数让服务器删除 API 调用缓存(django、DRF)

python - "ImportError: libcublas.so.10.0"仅在使用 GUI 时用于 Tensorflow

python - 正则表达式替换 : how to indent a variable number of lines in the middle of the rest of the match

python - uWSGI 共享内存的最小示例?

python - 如何在 django-cms 模板中使用调试变量?

python - selenium(使用 python/django)无法启动 firefox 浏览器实例

python - 使用 pandas 查找时间序列中重复发生的事件