2

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)

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

Comments

1

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)

2 Comments

Thanks, worked. What if I want to filter with many fields? for example, id, name, status, title? Should I add it separately for every field?
If you want to filter many fields in your current scenario you have to add it separately. Better you can switch to class based views and user Django rest framework's filter backed to filter multiple fields as mentioned in the previous answer by @Swift.
1

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.

4 Comments

You can accept your own answer :) but we could also have discussed in the comments and I would have updated it to better fit your use case. The difference in our answers is that with ReadOnlyModelViewset you could also get a single Author object, and you could also return more detailed information.
Oh, Sorry. I was trying to edit your answer yesterday and it was refused. and I completely forgot about the comment.
I cant review edits, even on my own posts, I dont have that privilege yet.
It was probably refused because answering you own question is actually encouraged if you figured it out in the course of receiving answers that we partially correct. It doesnt mean mine or other answers won't be read because it isn't accepted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.