Джанго медленно работает. фильтрация по нескольким параметрам - PullRequest
0 голосов
/ 19 мая 2011

У меня есть 3 модели:

class Author(models.Model):
    title = CharField()

class Genre(models.Model):
    title = CharField()

class Book(models.Model):
    title = CharField()
    author = ManyToManyField(Author)
    genre = ManyToManyField(Genre)

И у меня есть форма флажка (множественный выбор) со всеми жанрами и авторами, где значением флажка является идентификатор элемента (жанра или автора).

Цель: Показать книги с выбранными авторами или жанрами (без дубликатов)

Я могу сделать это двумя способами:

Первый способ:

if request.POST:
    book_list = Book.objects.all() #get all books from db
    books = []  

    request_list = request.POST.getlist('genre') #select list of genres in request
        for item in request_list:
            add_book = report_list.filter(genre=r_request) #queryset of book filtered by each genre 
            books.append(add_book) 
            book_list = book_list.exclude(genre=item)

    request_list = request.POST.getlist('author') #select list of authors in request
        for item in request_list:
            add_book = report_list.filter(author=item) #queryset of book filtered by each author 
            books.append(add_book) 
            book_list = book_list.exclude(author=item)
    return ...
        'books': books

Но этот путь очень медленный , когда я выбираю много авторов и жанров, потому что исключение очень медленное.

Второй способ:

Удалить book_list = book_list.exclude (...) и применить шаблонный тег {% ifchanged book.id%}

Но я думаю, это будет оченьслишком медленно, когда я получу более 1000 книг в результате запроса (книги)

Как быстро показать книги с выбранными авторами и жанрами?

Ответы [ 2 ]

3 голосов
/ 19 мая 2011

Вы просматриваете список, и для каждого из элементов списка вы запрашиваете SQL-запрос.

Каждый SQL-запрос выполняется по всей базе данных таблицы, чтобы получить результаты (если он не организован должным образом).

Таким образом, вы можете использовать поиск __ в для фильтрации из списка:

"книг, авторы изсписок и жанров из списка "

genre_list= request.POST.getlist('genre')
author_list = request.POST.getlist('author')
books = Book.objects.filter(genre__in=genre_list,author__in=author_list)

" книг, имеющих жанр или автора "

from django.db.models import Q
genre_list= request.POST.getlist('genre')
author_list = request.POST.getlist('author')
books = Book.objects.filter(Q(genre__in=genre_list) | Q(author__in=author_list))

Вы также можете прочитать Два или более __in фильтров в наборе запросов django ... Они используют объект Q для объединения запроса в один фильтр.

1 голос
/ 19 мая 2011

На мой взгляд:

genre_list= request.POST.getlist('genre')
author_list = request.POST.getlist('author')

query = None

if gender_list:
    gender_q = Q(genre__in=genre_list)
    query = gender_q

if author_list:
    author_q = Q(author__in=author_list)
    if gender_list:
       query|=author_q
    else:
       query = author_q

books = []
if query:
   books = Book.objects.filter(query).distinct()

http://docs.djangoproject.com/en/1.3/topics/db/queries/#complex-lookups-with-q-objects

...