Почему мой ViewSet продолжает цикл после использования для l oop ang с помощью get_object_or_404? - PullRequest
1 голос
/ 27 мая 2020

Я использую дополнительные действия для конечной точки image_tags для моих изображений. Я хочу выполнить POST и DELETE для каждого изображения image_tags. Я также смог использовать image_id для доступа к каждому изображению, используя lookup_field в моем изображении.

У меня есть эта конечная точка, например, для изображения IMG_123 image_tags:

localhost:8000/my_app/images/IMG_123/image_tags

Это мой code:

#models.py
class ImageTag(models.Model):
    name = models.CharField()
    description = models.CharField()

class Image(models.Model):
    image_id = models.CharField(unique=True)
    image_tags = models.ManyToManyField(ImageTag, blank=True)
    ...

#serializers.py
class ImageSerializer(serializers.ModelSerializer):

    class Meta:
        model = Image
        fields = '__all__'

class ImageTagSerializer(serializers.ModelSerializer):
    image_tags = serializers.StringRelatedField(many=True)

    class Meta:
        model = Image
        fields = ('image_tags',)

    def to_internal_value(self, data):
        return data

#views.py
class ImageExtraAction(viewsets.ModelViewSet):

    @action(detail=True, methods=['get', 'post', 'delete'])
    def image_tags(self, request, capture_id=None):
        print("REQ", request.data)
        capture = self.get_object()
        data = request.data.copy()

        image_tags = request.data.get('image_tags')
        print("IMG", image_tags)
        #print("LEN", len(image_tags))
        if image_tags:
            print("HERE")
            for tag in image_tags:
                obj_ = get_object_or_404(ImageTag, name=tag)
                data['image_tags'].append(obj_)

        print("DATA", data)
        serializer = ImageTagSerializer(capture, data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class ImageViewSet(ImageExtraAction, viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    lookup_field = 'image_id'
    ...

#urls.py
router.register(r'images', ImageViewSet, basename='image')

Когда я публикую:

{"image_tags": ["Urban", "Vegetation"]}

, я ожидаю, что они будут добавлены в поле image_tags. Однако у меня возникла проблема, поскольку он продолжает зацикливаться на кодовом блоке:

for tag in image_tags:
    obj_ = get_object_or_404(ImageTag, name=tag)
    data['image_tags'].append(obj_)

Почему это происходит? И как я могу это решить?

Я пробовал отладить его длину, его 2, как ожидалось, но когда дело доходит до l oop, он просто зацикливается бесконечно, поэтому мой запрос не выполняется.

1 Ответ

1 голос
/ 27 мая 2020

Причина, по которой цикл повторяется бесконечно, состоит в том, что вы добавляете его в конец своего списка.

Вот ваш список для каждой итерации.

1. ["Urban", "Vegetation"]
2. ["Urban", "Vegetation", "Urban"]
3. ["Urban", "Vegetation", "Urban", "Vegetation"]
4. ["Urban", "Vegetation", "Urban", "Vegetation", "Urban"]
...

Это продолжается без конца.

Лучший подход - запросить все image_tags одним запросом. Это также более производительно, поскольку у вас не будет специального запроса к базе данных для каждого тега.

data['image_tags'] = get_list_or_404(ImageTag, name_in=image_tags)

# or

data['image_tags'] = ImageTag.objects.filter(name_in=image_tags).all()

Чтобы создать его, если он отсутствует ...

# Query all image tags
tags = ImageTag.objects.filter(name_in=data['image_tags']).all()
# create a list of all existing tags
existing_tags = [tag.name for tag in tags]
# create a list of all tags in the request that don't exist.
missing_tags = [tag for tag in data['image_tags'] if tag not in existing_tags]

missing_tags это список тегов, которые не существуют. Вы можете просто перебирать его и создавать новые теги.

...