Accessing Request Object in Viewset and Serializer

2019-03-19 19:43发布

问题:

I want to access the request object in my Views.py and Serializers.py in DRF. My Views.py:

class ProductViewSet(viewsets.ReadOnlyModelViewSet):

    """
    This viewset automatically provides `list` and `detail` actions.
    """
    queryset = Product.objects.all()
    serializer_class = ProductSerializer(context={'request': request})

My Serializers.py:

class ProductSerializer(serializers.HyperlinkedModelSerializer):

    get_sr_price = serializers.SerializerMethodField('get_sr_price_func')

    def get_sr_price_func(self, obj):
        return self.request.user ??

    class Meta:
        model = Product
        fields = (
            'title', 'slug', 'product_stores', 'get_sr_price')

In Serializers.py I get ProductSerializer' object has no attribute 'request'. Also In views.py I get NameError: name 'request' is not defined

How do I access request object? Do I have to pass it from views to serializers? Also what's the difference between views.py and serializers.py? Generally I write all the business logic in Views.py ; here also should I do all the queries/filters in the views or should I do them in serializers or it doesn't make a difference. New to DRF please help.

回答1:

You don't need to include request object in the context as the generic views passes request object to the serializer context.

DRF Source code snippet:

# rest_framework/generics.py
def get_serializer_context(self):
    """
    Extra context provided to the serializer class.
    """
    return {
        'request': self.request, # request object is passed here
        'format': self.format_kwarg,
        'view': self
    }

In your serializer, you can access the request object using .context attribute.

The context dictionary can be used within any serializer field logic, such as a custom .to_representation() method, by accessing the self.context attribute.

class ProductSerializer(serializers.HyperlinkedModelSerializer):

    get_sr_price = serializers.SerializerMethodField('get_sr_price_func')

    def get_sr_price_func(self, obj):
        return self.context['request'].user # access the request object


回答2:

Serializers are the way external data is mapped from / to models (Django or simple Python classes).

Views are dealing with how the data will be shown. Throttling, pagination, authentication are managed by the view. They also handle the data set.

DRF provides a context to pass request specific data to the serializer without having to redefine the init. This is likely what you're looking for.