Nikko
Nikko

Reputation: 1572

How to have a custom endpoint for a model's field in Django?

I want to have an endpoint for every image I want to add tags in.

Suppose I have:

#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__'

#views.py
class ImageViewSet(viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    lookup_field = 'image_id'
    ...

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

I want to POST and DELETE image_tags in an endpoint such as:

localhost:8000/my_app/images/IMG_123/image_tags

where: IMG_123 is an Image

I think I will need a separate serializer and viewset for that. But more importantly I want to know how will I add such endpoint in the router in urls.py

I am looking for something like this:

router.register(r'<image>/image_tags', ImageTagViewSet, basename='image_tag')

NOTE: I was able to change Image endpoint using its image_id (instead of ID) because of lookup_field in ImageViewSet, thus can be:

localhost:8000/my_app/images/IMG_123/

Upvotes: 0

Views: 1384

Answers (2)

mahyar
mahyar

Reputation: 571

you can create custom endpoint for a viewset whit defining extra actions you will create a method with action decorator and the router of this viewset will create url from that method name for you for example:

from rest_framework.decorators import action

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

    @action(detail=True, methods=['post'])
    def image_tags(self, request, *args, **kwargs):
        image_instance = self.get_object() # image that it's id has been passed by url
        # you can now filter and get your ImageTags and serialize it with a serializer


this will create an endpoint like you want it localhost:8000/my_app/images/IMG_123/image_tags/

Upvotes: 2

skhynixsk
skhynixsk

Reputation: 194

views.py

class ImageViewSet(viewsets.ModelViewSet):
    image_id = self.kwargs['id']
    queryset = Image.objects.get(image_id=image_id)
    serializer_class = ImageSerializer
    lookup_field = 'image_id'
...

urls.py

router.register(r'(?P<id>[a-zA-Z0-9_]+)/image_tags$', ImageTagViewSet, basename='image_tag')

Upvotes: 1

Related Questions