Django url使用查询参数和单个视图来检索不同的对象集

时间:2017-12-10 12:49:34

标签: django django-rest-framework

我有一本模特书:

class Book(models.Model):
    book_id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=30)
    # A book can have multiple authors and an author can have multiple books
    author = models.ManyToManyField('Author')
    genre = models.CharField(max_length=20)
    isbn = models.CharField(max_length=20)
    summery = models.CharField(max_length=100, null=True)
    language = models.CharField(max_length=20, null=True)
    status = models.CharField(max_length=15, null=True)
    number_of_pages = models.IntegerField(blank=True)
    borrowed = models.DateField(auto_now=False, auto_now_add=False, null=True, blank=True)
    loan_period = models.IntegerField(default=14)
    due_date = models.DateField(auto_now=False, auto_now_add=False, null=True, blank=True)
    # A library has many books
    which_library = models.ForeignKey('Library', related_name='books', on_delete=models.CASCADE)

    #This helps to print in admin interface
    def __str__(self):
        return u"%s" % (self.title)

我有一个网址,它可以为我提供特定图书馆中的所有图书:

urlpatterns = [
    url(r'^books/(?P<library_id>[0-9]+)$', book_list),
]

我的视图会返回这些图书对象:

@api_view(['GET', 'POST'])
def book_list(request, library_id):
    """
    List all books in a specific library, or create a new book for a specific library
    """
    if request.method == 'GET':
        books = Book.objects.filter(which_library=library_id)
        print(books)
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

我的问题是:我可以,如果是,我该如何修改我的网址和视图,以便可以针对不同的查询参数过滤这个完整的图书清单以返回这些特定的图书,即如果我点击了{{1}这样的网址应该进一步过滤满足这些标准的书籍吗?建议这样做是好的做法还是为此目的写单独的网址和观点?

2 个答案:

答案 0 :(得分:1)

您可以从GET查询中获取查询网址,然后应用过滤器(如果存在)。

可以使用GET对象的request属性在Django中访问url查询参数中传递的值。

您的代码应如下所示:

@api_view(['GET', 'POST'])
def book_list(request, library_id):
    """
    List all books in a specific library, or create a new book for a specific library
    """
    if request.method == 'GET':
        genre_query = request.GET.get('genre', None)
        status_query = request.GET.get('status', None)

        books = Book.objects.filter(which_library=library_id)
        if genre_query:
            books = books.filter(genre=genre_query)
        if status_query:
            books = books.filter(status=status_query)

        print(books)
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

这是有效的,因为过滤器只是构建查询而不实际将其触发到数据库。因此,您可以在调用实际的提取命令之前链接过滤器(如print.all())。

  

建议这样做是好的做法还是为此目的写单独的网址和观点?

取决于用例,但使用查询参数的过滤器是在过滤时添加更多自定义的一种非常流行的方式。

答案 1 :(得分:1)

如果要将可选属性传递给视图处理程序,可以使用查询参数,这些参数可以通过'request.GET which is a QueryDict`访问,可以像字典一样访问。

重写你的例子:

if request.method == 'GET':
    books = Book.objects.filter(which_library = library_id)
    genre = request.GET.get('genre', None)
    status = request.GET.get('status', None)

    if genre:
       books = books.filter(genre = genre)
    if status:
       books = books.filter(status = status)

    ....    

注意在每个过滤器上重新分配book。这是因为过滤器或任何其他查询集操作返回新的查询集,并且不会更改现有的查询集。