Проблема при выполнении поиска с несколькими результатами. NoReverseMatch
Я делаю веб-приложение, которое использует API OpenLibrary, используя Django. В нем я выполняю поиск в API, если в результатах отображается более одной книги, я получаю такую ошибку:
NoReverseMatch at /search-results/
Отзыв для 'book_detail' с аргументами '('reina-roja-red-queen', 'Reina Roja / Red Queen')' не найден. Проверено 1 шаблон(ов): ['books/((?P
[-a-zA-Z0-9_]+)/(?P [^/]+)+)']
Мои файлы выглядят следующим образом:
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("search-results/", views.search_results, name="search_results"),
path("books/<slug:slug>/<str:title>", views.book_detail, name="book_detail"),
]
views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.utils.text import slugify
from books.api_library import search_book_by_author, search_book_by_title
from .models import Book
import requests
import json
def index(request):
"""
Index page
"""
if request.method == "POST":
type_search = request.POST.get("type_search")
search = request.POST.get("search")
if type_search == "title":
books_data = search_book_by_title(search).get("docs", [])
elif type_search == "author":
books_data = search_book_by_author(search).get("docs", [])
if not books_data:
books_data = []
request.session['search_results'] = books_data
return redirect('search_results')
return render(request, "books/index.html")
def search_results(request):
"""
View to display search results
"""
search_results = request.session.get('search_results', [])
books = []
for book in search_results:
slug = slugify(book.get("title", ""))
book_info = {
"title": book.get("title", ""),
"author": book.get("author_name", ""),
"isbn": book.get("isbn", ""),
"cover": book.get("cover", ""),
"publisher": book.get("publisher", ""),
"cover_url": f"https://covers.openlibrary.org/b/id/{book.get('cover_i', '')}-S.jpg",
"description": book.get("description", ""),
"publish_date": book.get("publish_date", ""),
"slug": slug
}
books.append(book_info)
return render(request, "books/search_results.html", {"books": books})
def book_detail(request, slug, title):
"""
Detail page
"""
print(title)
url = f"https://openlibrary.org/search.json?title={title}"
response = requests.get(url)
book_data = response.json()
print(book_data)
for book in book_data:
context = {
"title": book.get("title", ""),
"author": book.get("author_name", ""),
"isbn": book.get("isbn", ""),
"cover": book.get("cover", ""),
"publisher": book.get("publisher", ""),
"cover_url": f"https://covers.openlibrary.org/b/id/{book.get('cover_i', '')}-L.jpg",
"description": book.get("description", ""),
"publish_date": book.get("publish_date", ""),
}
return render(request, "books/book_detail.html", context)
index.html
{% extends "base.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<article class="main__article search">
<fieldset class="search__fieldset">
<p class="search__p">
<label for="search" class="search__label">Search</label>
<select name="type_search" id="type_search">
<option value="title">Title</option>
<option value="author">Author</option>
</select>
<input type="text" name="search" id="search" class="search__input">
<button type="submit" class="search__button">Search</button>
</p>
</article>
</form>
<br>
<article class="card">
{% for book in books %}
<figure class="card__figure">
<img src="{{ book.cover_url }}" class="card__img", alt="{{ book.title }}", height="200", width="200">
</figure>
<div class="card__div">
<h2 class="card__h2">{{ book.title }}</h2>
<p class="card__p">Author: {{ book.author }}</p>
<p class="card__p">Publish date: {{ book.publish_date }}</p>
<p class="card__p">Publisher: {{ book.publisher }}</p>
<a href="{% url 'book_detail' book.slug book.isbn %}" class="card__a" title="{{ book.title }}'}">View More</a>
</div>
{% endfor %}
</article>
{% endblock %}
search_results.html
{% extends "base.html" %}
{% block content %}
<h1>Search Results</h1>
{% if books %}
<ul>
{% for book in books %}
<li>
<a href="{% url 'book_detail' book.slug book.title %}">{{ book.title }}</a> by {{ book.author }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No results found.</p>
{% endif %}
{% endblock %}
book_detail.html
{% extends "base.html" %}
{% block content %}
<article class="book-details">
<h1>{{ title }}</h1>
<p><strong>Author(s):</strong> {{ author }}</p>
{% if cover_url %}
<img src="{{ cover_url }}" alt="Book Cover">
{% endif %}
<p><strong>Description:</strong> {{ description }}</p>
<!-- Otros detalles del libro que desees mostrar -->
</article>
{% endblock %}
Я хочу, чтобы мне показывали все результаты и я мог выбрать книгу и посмотреть в book_detail.html данные о ней.
Ваш второй параметр содержит косую черту, <str:…>
этого не позволяет <path:…>
, следует использовать конвертер путей:
path('books/<slug:slug>/<path:title>', views.book_detail, name='book_detail'),
При этом вы передаете заголовок с пробелами, косыми чертами и т. д. Это часто не очень хорошая идея, особенно в отношении оптимизации поисковых систем (SEO).