Search code examples
djangodjango-rest-frameworkdjango-views

Model's ImageField returning different results in viewset vs function-based view


I have a model for representing user ratings in a sample app I'm building using Django Rest Framework, and I'm weirdly getting different results for the ImageField depending on the kind of view I use to request the data.

Here is my model:

class Rating(models.Model):
    
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
    rating = models.IntegerField()
    review = models.CharField(max_length=500)
    recipe = models.ForeignKey(Recipe,on_delete=models.CASCADE, related_name='ratings')
    published_date = models.DateField(default=date.today)
    updated_date = models.DateField(default=date.today)
    photo = models.ImageField(upload_to='images/ratings/', blank=True)

I have the following Viewset set up for this model:

class RatingViewSet(viewsets.ModelViewSet):
    serializer_class = RatingSerializer
    lookup_fields = ('id', 'recipe')
    filter_backends = [DjangoFilterBackend]
    filterset_class = RatingFilter 

    queryset = Rating.objects.all()

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    def perform_update(self, serializer):
        serializer.save(updated_date=date.today())

and a separate simple function-based view to grab just the latest rating for the logged in user:

@api_view(['GET'])
def UserRating(request):
    recipe_id = request.query_params.get('recipe_id')

    try:
        rating = Rating.objects.filter(recipe=recipe_id, user=request.user).latest('updated_date')
        serializer = RatingSerializer(rating)

        return Response(serializer.data, status=status.HTTP_200_OK)
    except Rating.DoesNotExist:
        return Response({})

When I use the viewset to request the Ratings objects, the photo field is represented in each object like this:

"photo": "http://127.0.0.1:8000/media/images/ratings/image.jpg"

but when I use the function-based view the field doesn't show the server address, like this:

"photo": "/media/images/ratings/image.jpg"

Why would this field show up differently depending on the kind of view I'm using? Is there a config setting I'm missing that's getting used for one but not the other?


Solution

  • @Chowdahhh, it's possible that the issue arises because, in a ModelViewSet, the context is automatically passed to the serializer. However, in a function-based view, you are not explicitly passing the context. I suspect this might be the problem because the request object is typically present in the context, and the serializer may rely on it to create the full URL for the photo object.

    To resolve this, you can try passing the context to your function-based view like this:

    @api_view(['GET'])
    def UserRating(request):
        recipe_id = request.query_params.get('recipe_id')
    
        try:
            rating = Rating.objects.filter(recipe=recipe_id, user=request.user).latest('updated_date')
            serializer = RatingSerializer(rating,context={"request":request)
    
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Rating.DoesNotExist:
            return Response({})
    

    By explicitly passing the request to the serializer's context in your function-based view, it should behave more like the ModelViewSet, and you might resolve the issue you're facing.