API Query in Django Rest Framework

Question:

I have created an API from Database, I can view the API but I am unable to do a query via URL for example: 127.0.0.1:8000/author?author_id=9, I am not sure where to add the query code. I want to filter using fields. Here is my models.py

class AuthorAPI(models.Model):
    author_id=models.IntegerField()
    name=models.TextField()
    author_img_url=models.TextField()
    title=models.TextField()
    first_published_at=models.DateTimeField()
    excerpt=models.TextField()

    class Meta:
        db_table = 'view_author'

serializers.py

from rest_framework import serializers
from .models import SortAPI, AuthorAPI
class AuthorAPISerializer(serializers.ModelSerializer):
    class Meta:
        model=AuthorAPI
        fields='__all__'

views.py

from .serializers import APISerializer,AuthorAPISerializer
from .models import SortAPI, AuthorAPI
from rest_framework.response import Response
from rest_framework.decorators import api_view
@api_view(['GET'])
def getauthor(request):
    if request.method == 'GET':
        results = AuthorAPI.objects.all()
        serialize = AuthorAPISerializer(results, many=True)
        return Response(serialize.data)

Answers:

In your views, use a ModelViewset

And add the fliter_backend attribute:

filter_backends = [django_filters.rest_framework.DjangoFilterBackend]

See here in the docs:

https://www.django-rest-framework.org/api-guide/filtering/#setting-filter-backends

class AuthorViewset(viewsets.ReadOnlyModelViewset):
    serializer_class = AuthorAPISerializer
    queryset = AuthorAPI.objects.all()
    filter_backends = [django_filters.rest_framework.DjangoFilterBackend]

IMPORTANT

Using django_filter will require you to install additional requirements, buts its well worth it, see installation steps for django_filter here:

https://django-filter.readthedocs.io/en/stable/guide/install.html

And in your urls.py you need to register your viewser with a SimpleRouter as described in the docs here:

https://www.django-rest-framework.org/api-guide/viewsets/#example

Additionally, you’ll need to set the filterset_fields to tell DRF what fields you want to allow the user to filter with.

As specified in the docs here:

https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html#using-the-filterset-fields-shortcut

And important word of warning which might not be emphasised enough in the documentation is this point:

Note that using filterset_fields and filterset_class together is not supported.

Once complete, if you browse to /author you should see some filter controls available, et voila

Answered By: Swift

You can use request.GET to get data from URL parameters.

Give this a try

@api_view(['GET'])
def getauthor(request):
    if request.method == 'GET':

        results = AuthorAPI.objects.all()

        # get author_id from the url query parameter
        author_id = request.GET.get('author_id', None)
        
        #if author_id is present in the url query parameter then filter the resluts queryset based on the author_id
        if author_id:
            results = results.filter(author_id=author_id)

        serialize = AuthorAPISerializer(results, many=True)
        return Response(serialize.data)
Answered By: Sumithran

Thanks to Swift but there was some errors, viewsets.ReadOnlyModelViewset wasn’t working perfectly so I tried this

views.py

import django_filters.rest_framework
from django.contrib.auth.models import User
from rest_framework import generics,viewsets,filters
from django_filters.rest_framework import DjangoFilterBackend,OrderingFilter
from rest_framework.pagination import PageNumberPagination
from rest_framework.renderers import JSONRenderer

class CustomPagination(PageNumberPagination):
    page_size = 50
    page_size_query_param = 'page_size'
    max_page_size = 1000

class AuthorViewset(generics.ListAPIView):
    renderer_classes = [JSONRenderer]
    pagination_class = CustomPagination
    serializer_class = AuthorAPISerializer
    queryset = AuthorAPI.objects.all()
    filter_backends = [DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter]
    filterset_fields = ['name', 'id','author_id','status','title','first_published_at','story_type']
    search_fields=['id','author_id','name','title','first_published_at']
    ordering_fields=['id','author_id','name','title','first_published_at']

    class Meta:
        name="AuthorViewset"

I could have used Sumithran’s answer but it was a bit complex if I would like to allow multiple fields because for every field I had to add the same code with some modification which could increase code lines.