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 %} для перечисления элементов в отфильтрованном наборе запросов.