Django過濾和分頁

Django過濾和分頁


場景描述

在編寫WEB應用時,會通過類似www.example.com/books/的URL查詢書本列表。如果要查詢作者John的書籍呢,只要在URL後加過濾參數就好,www.example.com/books/?author=John

下面我們來看看Django的實現:
定義一個書本的模型,包含書本名、作者和價格。在後臺不指定條件的情況下,返回所有的書籍,指定作者名,就返回該作者名下的書籍。

# models.py
class Book(models.Model):
    name = models.CharField('名稱', max_length=128)
    author = models.CharField('作者', max_length=32)
    price = models.DecimalField('價格', decimal_places=2, max_digits=7)
    created_date = models.DateTimeField('添加時間', auto_now_add=True)

# views.py
from .models import Book
import json
import decimal
from datetime import datetime
from django.http import HttpResponse

class CustomEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return str(o)

        if isinstance(o, datetime):
            return o.strftime('%Y-%m-%d %H:%M:%S')

def get_books(request):
    author = request.GET.get('author', '')
    if author:
        books = Book.objects.filter(author=author).values('name', 'author', 'price', 'created_date')
    else:
        books = Book.objects.all().values('name', 'author', 'price', 'created_date')
    ret = {
        "total": books.count(),
        "data": list(books)
    }
    ret = json.dumps(ret, cls=CustomEncoder)
    return HttpResponse(ret)

#urls.py
from goods import views as goods_view

urlpatterns = [
    url('^books/', goods_view.get_books)
]

現在讓我們通過瀏覽器查看效果:
在瀏覽器輸入127.0.0.1:8000/books/返回的是提前在數據庫內存儲的四條記錄,加了過濾參數author,返回的是作者John名下的兩本書籍,是不是很簡單呢。

a
b

多個參數查詢

前面過濾只有一個author字段,如果有四五個參數呢,代碼就會像下面一樣。雖然可以實現需要的功能,但是重複的代碼比較多,使用django-filter就可以簡化這些操作。


def get_books(request):
    author = request.GET.get('author', '')
    created_date__gt = request.GET.get('created_date__gt', '')
    name = request.GET.get('name', '')
    books = Book.objects.all().values('name', 'author', 'price', 'created_date')

    if author:
        books = books.filter(author=author)
    if created_date__gt:
        books = books.filter(created_date__gt=created_date__gt)
    if name:
        books = books.filter(name=name)
    ret = {
        "total": books.count(),
        "data": list(books)
    }
    ret = json.dumps(ret, cls=CustomEncoder)
    return HttpResponse(ret)

django-filter介紹

Django-filter is a generic, reusable application to alleviate writing some of the more mundane bits of view code. Specifically, it allows users to filter down a queryset based on a model’s fields, displaying the form to let them do this.

django-filter一般與django的第三方框架restful framework組合使用, 我也是在使用
restful的時候,纔想到能不能單獨拿出來使用。詳細瞭解可以查詢官方文檔

下面是演示代碼,CustomFilter繼承FilterSet,使用方式類似於Django的ModelForm,在Meta中指定模型,fields則指定過濾的條件。exact指明字段相等,lt,gt則會與字段名組合成created_date__gtcreated_date__lt在filter()中使用,是不是很方便。django-filter其它功能和使用方式,在這裏就不詳細敘述了,感興趣的同學自己探索使用吧。

import django_filters

class CustomFilter(django_filters.FilterSet):
    class Meta:
        model = Book
        fields = {
            'name': ['exact'],
            'created_date': ['lt', 'gt', 'year'],
            'author': ['exact'],
            'price': ['lt', 'gt']
        }

def get_books(request):
    books = Book.objects.all().values('name', 'author', 'price', 'created_date')
    f = CustomFilter(request.GET, queryset=books)
    ret = {
        "total": f.qs.count(),
        "data": list(f.qs)
    }

    ret = json.dumps(ret, cls=CustomEncoder)
    return HttpResponse(ret)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章