I have two models: Library and a Book. A Library will have Many Books.
class Library(models.Model):
library_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
city = models.CharField(max_length=30)
address = models.CharField(max_length=80)
phone = models.CharField(max_length=30, blank=True, null=True)
website = models.CharField(max_length=60, blank=True, null=True)
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=30)
# A library has many books
which_library = models.ForeignKey('Library', related_name='books', on_delete=models.CASCADE)
reader = models.ManyToManyField('Reader', related_name='wishlist')
my serializers:
class LibrarySerializer(serializers.ModelSerializer):
class Meta:
model = Library
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
wishlist = ReaderSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = '__all__'
And my view:
class LibraryViewSet(viewsets.ModelViewSet):
queryset = Library.objects.all()
serializer_class = LibrarySerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.filter(which_library=library_id)
serializer_class = BookSerializer
My Urls:
router = routers.DefaultRouter()
router.register(r'libraries', LibraryViewSet)
router.register(r'books/(?P<library_id>[0-9]+)', BookViewSet)
urlpatterns = router.urls
my Library routes work correct. However for Books, I need to return the books only belonging to specific library. The default URL and all() returns all the books in database and can retrieve single by hitting books/1
.
How can I achieve this? I could do it previously with :
@api_view(['GET', 'POST'])
def books(request, library_id):
but now I want to do it with ModelViewSet.
Override get_queryset
method of you viewset where you can define to return specific books. This works like this.
class BookViewSet(viewsets.ModelViewSet):
serializer_class = LibrarySerializer
def get_queryset(self):
user = self.request.user
books = Book.objects.filter(which_library=self.kwargs['library_id'])
return books
You can also define list
and detail
methods where you can define your custom queries for Books. This is shown here.
Base name should be set like this.
router.register(r'books/(?P<library_id>[0-9]+)', BookViewSet, base_name='books')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With