Django - Correct method of consuming my own REST API internally in the views.py?

Alvaro Bataller :

I created a Django REST API using serializers, viewsets and routers. My end points looks something like this:

http://www.website.com/api/items
http://www.website.com/api/items/available

serializer.py (omitting imports)

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = '__all__'

viewsets.py (omitting imports)

class ItemViewSet(viewsets.ModelViewSet):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer

    @action(methods=['GET'], detail=False)
    def most_expensive(self, request):
        query = self.get_queryset().order_by('price').last()
        serialized = self.serializer_class(query)
        return Response(serialized.data)

Now I want to able to access this API from my views.py to render the HTML with the available items: This is the way im doing it right now:

views.py (omitting imports)

class ProductListView(View):
    template = 'store/product_list.html'

    def get(self, request):
        items = requests.get('http://127.0.0.1:8000/api/items/available')
        context = {'items': items}
        return render(request, self.template, context=context)

Using the requests modules I have a couple of concerns, after measuring I noticed there is a 0.015 second delay for that request to go through and if I ever change the API endpoint I would have to adjust it here since its hard coded.

I can get my items using:

Item.objects.filter(available=True)

Which gives me the result pretty much instantly but I'm writing all the queries twice (once in my API and once in my views.py)

Is there a better way of doing this like calling the viewset class directly and getting the data from there?

Many thanks!

Horatiu Jeflea :

Calling the API endpoint in the same app is not considered a good practise.

An option would be to call your viewset method directly, like in https://stackoverflow.com/a/51149806/290036

The other one that I recommend is to use the same codebase for your API and for the view.

def get_avaialble_items():
     items = Item.objects.filter(available=True)
     ...
     return items

# Use get_avaialble_items both in ItemViewSet and ProductListView

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=279163&siteId=1