Django Возврат набора запросов из таблицы базы данных путем фильтрации с использованием значений словаря

Моя цель - возвращать строки из таблицы books, используя значения, отправленные пользователем через форму поиска. Форма поиска содержит несколько полей автор, ISBN и название.

NB: В коде поле author является char, но преобразуется в ID на основе имени автора из-за отношения внешнего ключа.

В этом коде запрос get преобразован в Dictionary и трансформирован, чтобы позволить ему запросить данные из таблицы books.

def search(request):

    form = BooksForm()

    if request.method == 'GET':

        # convert get request to dictionary
         book_search = dict(request.GET)
         print("data before cleaning", book_search)

       #get the name from the dictionary get request
         author_name =request.GET['author']
       
        #get the author id from the author table
         author = Author.objects.filter(full_name__contains=author_name).values()

         #get author_id from author queryset
         author_id = author[0]['id']

      #update the dict with the author id to allow search in books models (foreing key)
         book_search['author'] = author_id
         print("data after cleaning",book_search)

         result_set = Book.objects.filter(**book_search)

         print("book search queryset",result_set)

Проблема: Когда я запрашиваю таблицу books с помощью словаря, он возвращает пустой набор запросов, а я хочу, чтобы он возвращал книги из таблицы. Есть ли у кого-нибудь идея, как я могу заставить код работать?

Прошу неразрешать фильтровать по произвольным ключам. Это делает представление чувствительным к подделке запросов, когда человек может, например, сделать запрос с author__gender в качестве ключа и F в качестве значения, и таким образом может раскрыть данные, которые вы, возможно, захотите скрыть.

Вы можете использовать библиотеку типа django-filter [GitHub], чтобы определить, как фильтровать набор запросов. Здесь вы можете сделать фильтр, который будет выглядеть следующим образом:

import django_filters

class BookFilter(django_filters.FilterSet):
    author = django_filters.CharFilter(
        field_name='author__full_name',
        lookup_expr='contains'
    )

    class Meta:
        model = Book
        fields = ['isbn']

При таком фильтре будут использоваться только ключи author и isbn из request.GET и, таким образом, игнорироваться другие ключи, которые, возможно, захотят отфильтровать конфиденциальные данные.

Вы можете использовать это с:

def search(request):
    book_filter = ProductFilter(request.GET)
    print('book search queryset', book_filter.qs)
    return render(request, 'name-of-template.html', {'book_filter': book_filter})

В шаблоне вы можете использовать {{ book_filter.form }} для формы, основанной на фильтре, и {% for item in book_filter.qs %} … {% endfor %} для перечисления элементов в отфильтрованном наборе запросов.

Вернуться на верх