it-swarm.com.de

Django REST: Hochladen und Serialisieren mehrerer Bilder

Ich habe 2 Modelle Task und TaskImage, bei denen es sich um eine Sammlung von Bildern handelt, die zum Objekt Task gehören.

Ich möchte, dass ich meinem Objekt Task mehrere Bilder hinzufügen kann, aber ich kann dies nur mit 2 Modellen tun. Derzeit kann ich beim Hinzufügen von Bildern keine Bilder hochladen und keine neuen Objekte speichern.

settings.py

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

serializers.py

class TaskImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = TaskImage
        fields = ('image',)


class TaskSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    images = TaskImageSerializer(source='image_set', many=True, read_only=True)

    class Meta:
        model = Task
        fields = '__all__'

    def create(self, validated_data):
        images_data = validated_data.pop('images')
        task = Task.objects.create(**validated_data)
        for image_data in images_data:
            TaskImage.objects.create(task=task, **image_data)
        return task

models.py

class Task(models.Model):
    title = models.CharField(max_length=100, blank=False)
    user = models.ForeignKey(User)

    def save(self, *args, **kwargs):
        super(Task, self).save(*args, **kwargs)

class TaskImage(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    image = models.FileField(blank=True)

Wenn ich jedoch eine Post-Anfrage mache:

 enter image description here

Ich bekomme folgenden Traceback:

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/exception.py" in Inner 41. response = get_response (request)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/base.py" in _get_response 187. response = self.process_exception_by_middleware (e, request)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/base.py" in _get_response 185. response = wrapped_callback (request, * callback_args, ** callback_kwargs)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/views/decorators/csrf.py" in wrapped_view 58. return view_func (* args, ** kwargs)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/viewsets.py" in Ansicht 95. self.dispatch zurückgeben (request, * args, ** kwargs)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py" im Versand 494. response = self.handle_exception (exc)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception 454. self.raise_uncaught_exception (exc)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py" im Versand 491. response = handler (request, * args, ** kwargs)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/mixins.py" in create 21. self.perform_create (serializer)

Datei "/Users/gr/Desktop/PycharmProjects/godo/api/views.py" in perform_create 152. serializer.save (user = self.request.user)

Datei "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/serializers.py" in save 214. self.instance = self.create (validated_data)

Datei "/Users/gr/Desktop/PycharmProjects/godo/api/serializers.py" in create 67. images_data = validated_data.pop ('images')

Ausnahmetyp: KeyError at/api/tasks/Ausnahmewert: 'images'

7
GRS

Beschreibung für das Problem
Der Ursprung der Ausnahme war eine KeyError, aufgrund dieser Aussage images_data = validated_data.pop('images'). Dies liegt daran, dass die validierten Daten keinen Schlüssel images haben. Dies bedeutet, dass die Bildeingabe die Bildeingaben vom Postboten nicht validiert.

Django-Post-Request-Speicher InMemmoryUpload in request.FILES, daher verwenden wir ihn zum Abrufen von Dateien. Außerdem möchten Sie mehrere Bilder gleichzeitig hochladen. Also, Sie müssen beim Hochladen Ihres Bildes (im Postboten) unterschiedliche Bildnamen verwenden .


Ändere deine serializer so, dass sie dir gefällt,

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    images = TaskImageSerializer(source='taskimage_set', many=True, read_only=True)

    class Meta:
        model = Task
        fields = ('id', 'title', 'user', 'images')

    def create(self, validated_data):
        images_data = self.context.get('view').request.FILES
        task = Task.objects.create(title=validated_data.get('title', 'no-title'),
                                   user_id=1)
        for image_data in images_data.values():
            TaskImage.objects.create(task=task, image=image_data)
        return task



Ich kenne Ihre Ansicht nicht, möchte aber ModelViewSet verwenden
bevorzugte Ansichtsklasse

class Upload(ModelViewSet):
    serializer_class = TaskSerializer
    queryset = Task.objects.all()


Postman Console  enter image description here

DRF-Ergebnis

{
        "id": 12,
        "title": "This Is Task Title",
        "user": "admin",
        "images": [
            {
                "image": "http://127.0.0.1:8000/media/Screenshot_from_2017-12-20_07-18-43_tNIbUXV.png"
            },
            {
                "image": "http://127.0.0.1:8000/media/game-of-thrones-season-valar-morghulis-wallpaper-1366x768_3bkMk78.jpg"
            },
            {
                "image": "http://127.0.0.1:8000/media/IMG_212433_lZ2Mijj.jpg"
            }
        ]
    }



UPDATE
Dies ist die Antwort auf Ihren Kommentar. In Django wird reverse foreignKey mit _set erfasst. siehe dieses offizielle Dokument . Hier stehen Task und TaskImage in einer OneToMany-Beziehung. Wenn Sie also eine Task-Instanz haben, können Sie alle zugehörigen TaskImage-Instanzen mit dieser reverse look-up-Funktion abrufen
hier ist das Beispiel

task_instance = Task.objects.get(id=1)
task_img_set_all = task_instance.taskimage_set.all()

Hier ist dieser task_img_set_all gleich TaskImage.objects.filter(task_id=1)

9
JPG

Sie haben read_only im verschachtelten Feld TaskImageSerializer auf true gesetzt. Es werden dort also keine validierten_Daten vorhanden sein.

0
kevswanberg