Django休息ModelViewSet过滤对象

时间:2018-01-04 11:06:32

标签: django django-rest-framework

我有两个模型:图书馆和书。图书馆会有很多书。

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')

我的序列化器:

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__'

我的观点:

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

我的网址:

router = routers.DefaultRouter()
router.register(r'libraries', LibraryViewSet)
router.register(r'books/(?P<library_id>[0-9]+)', BookViewSet)

urlpatterns = router.urls

我的图书馆路线工作正常。但是对于Books,我需要返回仅属于特定库的书籍。默认URL和all()返回数据库中的所有书籍,并可通过点击books/1来检索单个书籍。

我怎样才能做到这一点?我之前可以用:

@api_view(['GET', 'POST'])
def books(request, library_id): 

但现在我想用ModelViewSet做。

2 个答案:

答案 0 :(得分:4)

覆盖视图集的get_queryset方法,您可以在其中定义以返回特定图书。这样就可以了。

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

您还可以定义listdetail方法,您可以在其中定义图书的自定义查询。这显示为here

基本名称应该像这样设置。

router.register(r'books/(?P<library_id>[0-9]+)', BookViewSet, base_name='books')

答案 1 :(得分:1)

您可以将detail_route添加到库vewset:

@detail_route(methods=['GET'])
def books_list(self, request, pk=None):
    library = self.get_object()   
    books = library.books.all()
    serializer = serializers.BookSerializer(books, many=True)
    response = Response(serializer.data)
    return response

现在应该使用此网址libraries/{libriry_id}/books_list列出图书馆的图书。