Мне удалось использовать дополнительные действия для создания конечной точки, когда я хочу отправить ImageTag (поле ManyToMany) на свое изображение. Я также смог использовать lookup_field
для создания CharField вместо pk для доступа к каждому изображению.
Это моя конечная точка образца при добавлении ImageTag:
POST localhost:8000/my_app/images/IMG_123/image_tags/
Я могу отправить что-то вроде POST до конечной точки:
{"image_tags": ["Urban", "Vegetation"]}
Это мой исходный код:
#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 CaptureExtraAction(viewsets.ModelViewSet):
@action(detail=True, methods=['get', 'post', 'delete'])
def image_tags(self, request, image_id=None):
image = self.get_object()
data = request.data.copy()
image_tags = request.data.get('image_tags')
if image_tags:
data['image_tags'] = []
for tag in image_tags:
obj_, created = ImageTag.objects.get_or_create(
defaults={'name': tag},
name__iexact=tag
)
image.image_tags.add(obj_)
data['image_tags'] = image.image_tags.all()
serializer = ImageTagSerializer(image, 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 ImageTagViewSet(ImageExtraAction, viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
lookup_field = 'image_id'
...
#urls.py
router.register(r'images', ImageTagViewSet, basename='image')
Моя следующая задача - разрешить методу DELETE удалить ImageTag из объекта. Например, я хочу удалить «Город» в ImageTag для изображения IMG_123, я хочу иметь такую конечную точку:
DELETE localhost:8000/my_app/images/IMG_123/image_tags/Urban
также может быть:
DELETE localhost:8000/my_app/images/IMG_123/image_tags/?name=Urban
Как будет добавить это в мой текущий набор дополнительных действий?