Django rest framework self nesteg query - django

I'm using DRF. How can I get hierarchical JSON by django ORM?
what the query should look like?
CategoryModel.objects.filter(active=True).select_related() or prefetch_related()?
I have model that looks like this:
class Category(models.Model):
parent = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True)
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True, default='', blank=True)
active = models.BooleanField(default=True)
serializers:
class ParentCategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class CategoryListSerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['name', 'slug', 'parent']
parent = ParentCategorySerializer(many=True)
I want to get something like this (greater depth possible):
{
"name": "First category",
"slug": "first-category",
"subcategories": [
{
"name": "First subcategory one",
"slug": "first-subcategory-one",
"subcategories": null
},
{
"name": "First subcategory two",
"slug": "first-subcategory-two",
"subcategories": null
},
]
},
{
"name": "Second category",
"slug": "second-category",
"subcategories": []
}

views.py:
from rest_framework.viewsets import ModelViewSet
from .models import Category
from .serializers import CategorySerializer
class CategoryViewSet(ModelViewSet):
queryset = Category.objects.filter(parent=None)
serializer_class = CategorySerializer
serialisers.py:
from rest_framework import serializers
from .models import Category
from django.db.models import CharField, Value
class CategorySerializer(serializers.ModelSerializer):
subcategories = serializers.SerializerMethodField()
def get_subcategories(self, obj):
return (
Category.objects.filter(parent_id__isnull=False, parent_id=obj.id)
.annotate(subcategories=Value(None, output_field=CharField()))
.values("name", "slug", "subcategories")
)
class Meta:
model = Category
fields = ["name", "slug", "subcategories"]
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("category/", views.CategoryViewSet.as_view({"get": "list"})),
]

Related

DRF how to get items grouping by categories

I understand that my question is repeated often, but I'm stuck with this.
I want to make a simple API with DRF. I have two models:
models.py
class Rubrics(models.Model):
id = models.AutoField(primary_key=True)
rubric = models.CharField(max_length=255, blank=True, null=True)
class Books(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, blank=True, null=True)
author = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
rubrics = models.ForeignKey('Rubrics', on_delete=models.DO_NOTHING, related_name='books', blank=True, null=True)
I'd like to view serialized results like this:
[
rubric1: [
{
title: "title1",
author:"author1"
},
book_obj2,
so on
],
rubric2: [
book_obj4,
book_obj5
]
]
views.py
class BooksByRubricView(APIView):
"""List of books by rubrics"""
def get(self, request):
last_date = Books.objects.latest("date").date
books_last = Books.objects.filter(date=last_date)
serializer = RubricsSerializer(books_last, many=True)
return Response(serializer.data)
I try a lot of examples in this theme:
#sorry this garbage
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#fields = ("title",)
exclude = ()
class RubricsSerializer(serializers.ModelSerializer):
rubrics = BookSerializer(read_only=True)
class Meta:
model = Rubrics
fields = ("rubrics",)
#exclude = ()
"""
class RubricSerializer(serializers.ModelSerializer):
#rubrics = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
#books = RecursiveSerializer(many=True)
#print(books)
rubrics = RubricSerializer(read_only=True)
#books = BooksListSerializer(many=True)
class Meta:
model = Books
fields = ("title", "rubrics",)
#fields = ['rubric', 'rubrics']
#fields = ['books', 'rubrics']
"""
But maybe I don't understand the principles of reverse relationships and serializing in DRF. Please, tell me WAIDW. Thanks.
UPD.
I want to operate only on specified sets of data (for example, work with the last uploaded books), not on the whole table Books. So I want to view only rubrics, that are in this set, not all rubrics from table Rubrics. Yes, books have only one rubric id in a specified field, and the rubric has a one-to-many relationship to books.
Well, that's JSON I want to see (of course, all characters appearing in this work, are fictitious. Any resemblance to actual persons, living or dead, is purely coincidental.):
{
"rubric1": [{
"author": "Marley W. Watkins",
"title": "A Step-By-Step Guide to Exploratory Factor Analysis with Stata"
}, {
"author": "Robert E. Davis",
"title": "Auditing Information and Cyber Security Governance; A Controls-Based Approach"
}, {
"author": "Gerhard X. Ritter, Gonzalo Urcid",
"title": "Introduction to Lattice Algebra: With Applications in AI, Pattern Recognition, Image Analysis, and Biomimetic Neural Networks"
}],
"rubric2": [{
"author": "Richard Cross and JT Paasch",
"title": "The Routledge Companion to Medieval Philosophy"
}, {
"author": "Nicholas Allott (editor), Terje Lohndal (editor), Georges Rey (editor)",
"title": "A Companion to Chomsky"
}, {
"author": "Olakunle George",
"title": "A Companion to African Literatures"
}, {
"author": "Tim Byrnes, Ebubechukwu O. Ilo-Okeke",
"title": "Quantum Atom Optics: Theory and Applications to Quantum Technology"
}],
"rubric3": [{
"author": "Hiroyoshi Naito",
"title": "Organic Semiconductors for Optoelectronics"
}, {
"author": "Bassem R. Mahafza, Scott C. Winton",
"title": "Handbook of Radar Signal Analysis"
}, {
"author": "Sean McManus, Mike Cook",
"title": "Raspberry Pi For Dummies, 4th Edition"
}]
}
I realize it in plain Django:
class BooksByRubricView(APIView):
"""List of books by rubrics"""
def get(self, request):
last_date = Books.objects.using('books').latest("date").date
books_last = Books.objects.using('books').filter(date=last_date)
categories = []
res_dict = {}
for item in books_last:
categories.append(item.rubrics_id)
categories = set(categories)
for item in categories:
temp_list = []
temp_qs = books_last.filter(rubrics_id=item)
for i in temp_qs:
temp_list.append({"author": i["author"], "title": i["title"]})
res_dict["rubric"+str(item)]=list(temp_list)
# res = json.dumps(res_dict)
return JsonResponse(res_dict, safe=False, json_dumps_params={'ensure_ascii': False})
can I realize it with DRF serializers or simplest way is not f*cking any brains and return JSON as above?
Update2:
Well, after some magic with serializers and generic.APIView I've got a result not exactly expected, but very closest to that. Example (of course, all characters appearing in this work, are fictitious. Any resemblance to real persons, living or dead, is purely coincidental)
views.py
class BooksByRubricView2(generics.ListAPIView):
"""Books grouped by rubrics"""
serializer_class = RubricsSerializer2
queryset = Rubrics.objects.all()
#OR without generic
class BooksByRubricView3(APIView):
def get(self, request):
r = Rubrics.objects.all()
serializer=RubricsSerializer2(r,many=True)
return Response(serializer.data)
serializers.py
class FilteredListSerializer(serializers.ListSerializer):
"""Serializer to filter Book table, look for latest date for every rubric"""
def to_representation(self, data):
latest_data = data.latest("date").date
data = data.filter(date=latest_data)
return super(FilteredListSerializer, self).to_representation(data)
class BookSerializer2(serializers.ModelSerializer):
class Meta:
model = Books
list_serializer_class = FilteredListSerializer
fields = (
"title",
"author",
"date")
class RubricsSerializer2(serializers.ModelSerializer):
books = BookSerializer2(many=True, read_only=True)
class Meta:
model = Rubrics
fields = ("rubric", "books",)
result:
[
{
"rubric": "Computers",
"books": [
{
"title": "A Step-By-Step Guide to Exploratory Factor Analysis with Stata",
"author": "Marley W. Watkins",
"date": "2021-08-08"
},
{
"title": "Auditing Information and Cyber Security Governance; A Controls-Based Approach",
"author": "Robert E. Davis",
"date": "2021-08-08"
}
]
},
{
"rubric": "Education",
"books": [
{
"title": "The Routledge Companion to Medieval Philosophy",
"author": "Richard Cross and JT Paasch",
"date": "2021-08-08"
}
]
},
so on
}
It's a dirty way because every Rubric from table Rubrics creates its own query to table Books and each Rubric has its latest date. But DRF filtering will be the next step.
There is no field rubrics in Rubrics model, available fields are:
id,rubric from model itself,
books_set which represent all books that have FK reference to that Rubrics instance. Take a look at this official docs
Book have one rubric (rubrics foreign key), and rubrics have multiple books (books_set). I would also suggest changing FK name from rubrics to rubric since there can be only one.
Try this and work from there:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#fields = ("title",)
exclude = ()
class RubricsSerializer(serializers.ModelSerializer):
class Meta:
model = Rubrics
fields = ("books_set",)
#exclude = ()
First i've tried to get the result that you wanted using your view and just dit not worked! So I've created another view:
from .serializers import *
from rest_framework import generics
from .models import *
class BooksByRubricView(generics.ListAPIView):
serializer_class = RubricsSerializer
queryset = Rubric.objects.all()
# You should try!
And course I also had to create a path (Just for tests! Ignore it!):
from django.urls import path
from .views import BooksByRubricView
urlpatterns = [
path('books/', BooksByRubricView.as_view(), name='books')
]
In your models:
from django.db import models
class Rubric(models.Model):
id = models.AutoField(primary_key=True) # Do not use plural in the models name!
rubric_name = models.CharField(max_length=255, blank=True, null=True)
class Meta:
ordering = ['id'] # Create a ordering!
def __str__(self):
return self.rubric_name
class Book(models.Model):
rubric = models.ForeignKey(Rubric, related_name='rubrics', on_delete=models.CASCADE)
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, blank=True, null=True)
author = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
class Meta:
ordering = ['id'] # Create a ordering!
In your serializers.py:
from rest_framework import serializers
from .models import *
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = (
"title",
"author",
"date"
)
class RubricsSerializer(serializers.ModelSerializer):
rubrics = BookSerializer(many=True, read_only=True)
class Meta:
model = Rubric
fields = (
"id", # Put an Id if you want!
"rubrics",
)
Maybe the only problem was with your view! So I just did all this to get the result that you want but localy; images of the result:

why many to many field relationship menu are not showing the proper fields?

recently i am converting my project into DRF and the serializer.py is following:
from rest_framework import serializers
from .models import Menu,MenuCategory,MenuItem
class MenuItemSerializer(serializers.ModelSerializer):
class Meta:
model = Menu
fields = ['name', 'additional_text', 'order']
class MenuCategorySerializer(serializers.ModelSerializer):
menuitem = serializers.StringRelatedField(many=True, read_only=True)
class Meta:
model = MenuCategory
fields = ['order', 'name', 'description','menuitem']
def create(self, MenuCategory, MenuItem,validated_data):
menucategory=MenuCategory.objects.create(**validated_data)
item_data = validated_data.pop('menuitem')
for it_data in item_data:
MenuItem.objects.create(menucategory=menucategory, **item_data)
return menucategory
class MenuSerializer(serializers.ModelSerializer):
menucategory = serializers.StringRelatedField(many=True, read_only=True)
class Meta:
model = Menu
fields = ['name', 'additional_text', 'order','menucategory']
def create(self,MenuCategory, Menu, validated_data):
category_data = validated_data.pop('menucategory')
menu= Menu.objects.create(**validated_data)
for cat_data in category_data:
MenuCategory.objects.create(menu=menu, **category_data)
return menu
When i browse http://localhost:8000/api/, it shows:
[
{
"name": "Breakfast",
"additional_text": "Served between 8:00am and11:00am",
"order": 1,
"menucategory": [
"MenuCategory object (3)",
"MenuCategory object (4)"
]
},
{
"name": "Lunch",
"additional_text": "Served between 12:00pm and 3:00pm",
"order": 2,
"menucategory": [
"MenuCategory object (1)",
"MenuCategory object (5)",
"MenuCategory object (7)"
]
},
{
"name": "Dinner",
"additional_text": "Served between 6:00pm and 10:00pm",
"order": 3,
"menucategory": [
"MenuCategory object (2)",
"MenuCategory object (6)",
"MenuCategory object (8)"
]
},
{
"name": "Drinks",
"additional_text": "Happy hour 3:00pm to 6:00 pm",
"order": 4,
"menucategory": [
"MenuCategory object (9)",
"MenuCategory object (10)",
"MenuCategory object (11)"
]
}
]
but the list shouldn't be showing this menuobject kind of things. it should show the item and category name with the price and other fields. here is my views.py:
from rest_framework import generics
from .models import Menu,MenuCategory,MenuItem
from .serializers import MenuCategorySerializer,MenuSerializer,MenuItemSerializer
class ListMenuCategory(generics.ListAPIView):
queryset = MenuCategory.objects.order_by('order')
serializer_class = MenuCategorySerializer
class ListMenu(generics.ListAPIView):
queryset = Menu.objects.order_by('order')
serializer_class = MenuSerializer
class ListMenuItem(generics.ListAPIView):
queryset = MenuItem.objects.order_by('order')
serializer_class = MenuItemSerializer
and my models.py as followed:
from django.db import models
class MenuItem(models.Model):
menu_category = models.ManyToManyField('MenuCategory', related_name='menuitem',help_text='The menus that this category belongs to, i.e. \'Lunch\'.')
name = models.CharField(max_length=48, help_text='Name of the item on the menu.')
description = models.CharField(max_length=128, null=True, blank=True, help_text='The description is a simple text description of the menu item.')
order = models.IntegerField(default=0, verbose_name='order', help_text='The order is to specify the order in which items show up on the menu.')
price = models.FloatField(help_text='The price is the cost of the item.')
class Meta:
ordering = ['order', 'name']
def __unicode__(self):
return self.name
class MenuCategory(models.Model):
menu = models.ManyToManyField('Menu', related_name='menucategory',help_text='The menus that this category belongs to, i.e. \'Lunch\'.')
name = models.CharField(max_length=48, help_text='Name of the item on the menu.')
description = models.CharField(max_length=128, null=True, blank=True, help_text='The description is a simple text description of the menu item.')
order = models.IntegerField(default=0, verbose_name='order', help_text='The order is to specify the order in which items show up on the menu.')
class Meta:
ordering = ['order', 'name']
def __unicode__(self):
return self.name
class Menu(models.Model):
name = models.CharField(max_length=32, verbose_name='menu category name')
additional_text = models.CharField(max_length=128, null=True, blank=True, help_text='The additional text is any bit of related information to go along with a menu category, i.e. the \'Pasta\' category might have details that say \'All entrees come with salad and bread\'.')
order = models.IntegerField(default=0, help_text='The order is the order that this category should appear in when rendered on the templates.')
class Meta:
ordering = ['order', 'name']
def __unicode__(self):
return self.name
how should i do the query and how can i fix my DRF api list?
You should use the serializer for the related model if you wish to use the related serializer, not a serializers.StringRelatedField
class MenuSerializer(serializers.ModelSerializer):
menucategory = MenuCategorySerializer(many=True, read_only=True)

how to override returned serializer object that is returned with the response django rest framework serializer

I have a django rest framework project. I want to override the returned json object structure when a get request is made to display a specific way not similar to the database structure.
My current return object is displayed like so:
{
"id": 9,
"namespace": "steve",
"path": "something/another",
"value": "this is a value",
"person": 1
},
{
"id": 11,
"namespace": "namespace1",
"path": "path2",
"value": "anyoher value",
"person": 2
},
{
"id": 12,
"namespace": "namespace1",
"path": "path3",
"value": "this dsiaalks",
"person": 2
},
{
"id": 13,
"namespace": "namespace2",
"path": "path4",
"value": "asdfasdfasdf",
"person": 2
},
I want to switch the
"person":2
to display
"user":{
"userId":testUser
}
testUser is the username of the user with id 2 *
THis is my current serailzer:
from rest_framework import serializers
from .models import Preference
from django.contrib.auth.models import User
class PreferenceSerializer(serializers.ModelSerializer):
person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)
class Meta:
model = Preference
fields = ('id', 'namespace', 'path', 'value', 'person')
and this is the current model:
from django.db import models
from django.contrib.auth.models import User
from owf_framework.people.models import Person
class Preference(models.Model):
id = models.BigAutoField(primary_key=True, null=False)
version = models.BigIntegerField(default=1, null=False)
path = models.CharField(max_length=200, null=False)
namespace = models.CharField(max_length=200, null=False)
value = models.TextField(null=False)
user_id = models.BigIntegerField(null=False, default=1)
person = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.namespace
class Meta:
db_table = 'preference'
the field person is a foreign key for user.
Hope this helps:
serializers.py
from rest_framework import serializers
from .models import Preference
from django.contrib.auth.models import User
class PreferenceSerializer(serializers.ModelSerializer):
person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)
class Meta:
model = Preference
fields = ('id', 'namespace', 'path', 'value', 'person')
def to_representation(self, instance):
ret = super(PreferenceSerializer, self).to_representation(instance)
# check the request is list view or detail view
is_list_view = isinstance(self.instance, list)
if is_list_view:
person_id = ret.pop('person', None)
user_obj = User.objects.filter(id=person_id).first()
user_name = user_obj.username if user_obj else ""
extra_ret = {
"user": {
"userId": user_name
}
}
ret.update(extra_ret)
return ret
i think you can use models method. example:
models.py
from django.db import models
from django.contrib.auth.models import User
from owf_framework.people.models import Person
class Preference(models.Model):
id = models.BigAutoField(primary_key=True, null=False)
version = models.BigIntegerField(default=1, null=False)
path = models.CharField(max_length=200, null=False)
namespace = models.CharField(max_length=200, null=False)
value = models.TextField(null=False)
user_id = models.BigIntegerField(null=False, default=1)
person = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.namespace
def get_person(self):
return self.person.username
class Meta:
db_table = 'preference'
then in you're serializer:
from rest_framework import serializers
from .models import Preference
from django.contrib.auth.models import User
class PreferenceSerializer(serializers.ModelSerializer):
person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)
class Meta:
model = Preference
fields = ('id', 'namespace', 'path', 'value', 'person', 'get_person')
My advice is not to override serializers. Serializers should only serialize data that you have, as is. In your case, you can create a ViewSet (not a ModelViewSet), define your query with filters in the retrieve() method, and then easily configure the responses you need.
I think this helps you:
from rest_framework.serializers import ModelSerializer, SerializerMethodField
class PrefrenceSerializer(ModelSerializer):
user = SerializerMethodField()
class Meta:
model = Prefrence
exclude = ['person']
def get_user(self, obj):
return {
"userId": obj.person.userId
}

How to perform nested serialization in Django?

I am new to Django.I am using Django REST Framework and I need to get json from serializers in the following format:
{
"result" : 200,
"categories" : [{
"id" : "V001",
"name": "Vehicles",
"description": "All types of motor and non-motor vehicles",
"icon": "http://images.maa.ae/static/icons/vehicles.png",
"subcategories": [{
"id" : "V00101",
"name": "Cars",
"description": "Motor Cars",
"subcategories": [{
"id" : "V0010101",
"name": "Passenger Cars",
"description": "All types of passenger cars"
}]
},
{
"id" : "V00102",
"name": "Bikes",
"description": "Bikes",
"subcategories": [{
"id" : "V0010201",
"name": "Motor Bikes",
"description": "All kinds of motor bikes"
},
{
"id" : "V0010202",
"name": "Sports Bikes",
"description": "All kinds of sports bikes"
}]
}]
}]
}
My Model class is:
class Category(models.Model):
_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=128)
description = models.CharField(max_length=150,null=True, blank=True)
icon = models.ImageField(upload_to='icons',null=True, blank=True)
parent_id = models.ForeignKey('self', null=True, blank=True)
and my serializers class is:
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = ('_id', 'name', 'description', 'icon')
From above implementation I can get Array of Category objects in JSON format.
But I don't know how can I include 'subcategories' in my serializer class.Please help me to get an output similar to json shown in above format.
Use Django Rest Framework.
http://www.django-rest-framework.org/
Keep your code DRY
from rest_framework import serializers
class CategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = Categories
Views
from rest_framework import viewsets
from .serializers import CategoriesSerializer
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Categories.objects.all()
serializer_class = CategoriesSerializer
Example
models.py:
class Sprints(models.Model):
name = models.CharField(default='', blank=True, max_length=90)
description = models.TextField(default='')
class Tasks(models.Model):
date_posted = models.DateTimeField(auto_now_add=True)
name = models.CharField(default='', blank=True, max_length=90)
end = models.DateTimeField(null=True, blank=True)
sprint = models.ForeignKey(Sprints, related_name='tasks')
class Meta:
ordering = ['-date_posted']
unique_together = ['name', 'sprint']
serializers.py:
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Tasks
fields = ('id', 'name', 'date_posted', 'end')
class SprintSerializer(serializers.ModelSerializer):
tasks = TaskSerializer(many=True, read_only=True)
class Meta:
model = Sprints
fields = ('id', 'name', 'description', 'tasks')
views.py
class SprintsViews(viewset.ModelViewSet):
queryset = Sprints.objects.all()
serializer_class = SprintSerializer
You can also add a slug field to the models to make them easier to deal with, but this is how for now :)
You should consider having a look at THIS. The usage of depth meta attribute enables you to retrieve related objects to the depth you set.
By doing so, it automatically retrieves nested data.
It is very convenient to avoid using serializers in both sides and thus having ImportError caused by cycles too.
Use related_name and on_delete on your parent_id field in models.py file
class Category(models.Model):
_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=128)
description = models.CharField(max_length=150,null=True, blank=True)
icon = models.ImageField(upload_to='icons',null=True, blank=True)
parent_id = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE)
Now add the packege pip install djangorestframework-recursive on your project
serializers.py:
##################################
from rest_framework_recursive.fields import RecursiveField
##################################
class CategorySerializer(serializers.ModelSerializer):
children = RecursiveField(many=True)
class Meta:
model = Category
fields = ('_id', 'name', 'description', 'icon', 'parent_id', 'children')
views.py (Serializers view file):
class CategoryListAPIView(generics.ListAPIView):
serializer_class = CategorySerializer
queryset = Category.objects.filter(parent_id__isnull=True)
urls.py:
############################
############################
urlpatterns = [
path('category/', views.CategoryListAPIView.as_view(), name="categoryAPI"),
######################################
]

Django Rest Framework (GET filter on ManyToMany field)

I am trying to figure out how to filter a ManyToMany field by value. In Django, it is as simple as queryset.filter(m2mfield__name), but I can't quite figure out what I am missing. I am using the Django Rest Framework, and the DjangoFilterBackend.
Models:
class City(models.Model):
name = models.CharField(max_length=80)
class State(models.Model):
name = models.CharField(max_length=50)
cities = models.ManyToManyField(City)
Filters:
import django_filters
class StateFilter(django_filters.FilterSet):
cities = django_filters.CharFilter(
name='cities__name',
lookup_type='contains',
)
class Meta:
model = State
fields = ('name', 'cities')
Serializers:
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields = ('name', )
class StateSerializer(serializers.ModelSerializer):
cities = CitySerializer(many=True)
class Meta:
model = State
fields = ('name', 'cities')
filter_class = StateFilter
View:
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .serializers import StateSerializer
class StateList(ListAPIView):
queryset = State.objects.all()
serializer_class = StateSerializer
filter_fields = ('name', 'cities')
The output for ../api/states/ is currently:
[
"name": "Florida",
"cities": [
"name": "Tampa",
"name": "St. Petersburg",
"name": "Orlando"
],
"name": "North Carolina",
"cities": [
"name": "Raleigh",
"name": "Charlotte",
"name": "Greensboro"
]
]
How can I filter the cities via a GET call by name such as:
../api/states/?cities=Charlotte
The result of the above should be:
[
"name": "North Carolina",
"cities": [
"name": "Raleigh",
"name": "Charlotte",
"name": "Greensboro"
]
]
Well, I found out what I was doing wrong. It was in the view. I had not declared filter_class on the view:
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .serializers import StateSerializer
from .filters import StateFilter
class StateList(ListAPIView):
queryset = State.objects.all()
serializer_class = StateSerializer
filter_fields = ('name', 'cities')
filter_class = StateFilter # This was missing
I accidentally placed it on the serializer instead.