Django - Пагинация не работает для последней страницы
На моем сайте я хочу показать вина с пагинацией, 9 страниц на странице (предположим, у нас 22 вина). Вина хранятся в интерфейсе администратора, каждое вино имеет такие поля, как название, тип, описание и ImageField для загрузки соответствующих изображений. Однако, когда я нажимаю на третью (последнюю) страницу, появляется следующая страница:
Ошибка значения в /page-name/
Атрибут 'image' не имеет связанного с ним файла.
Метод запроса: GET
URL запроса: http://localhost/page-name/?page=3
Версия Django: 5.0.4
Тип исключения: ValueError
Значение исключения:
Атрибут 'image' не имеет связанного с ним файла.
Местоположение исключения: [путь].venv\Lib\site-packages\django\db\models\fields\files.py, строка 41, in _require_file
Поднято во время: [app-name].views.wines_page_red
В консоли я получаю следующее предупреждение: TypeError: 'ImageFieldFile' object is not subscriptable
...и куча исключений. Я новичок в Django и не понимаю, что может вызвать проблему, так как все изображения для соответствующих товаров загружены. Где-то читал, что метод, который я использовал для пагинации, может быть нестабильным, поэтому я попытался упорядочить вина по их названию, и теперь 2-я страница выдает ту же ошибку. Вот вид, url-часть и шаблон:
Вид:
def wines_page_red(request):
red_wines_list = Wine.objects.filter(type='Red')
paginator = Paginator(red_wines_list, 9)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'red-wines.html', {'page_obj': page_obj})
Часть url на уровне проекта:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('[app-name].urls')),
] + static(django.conf.settings.MEDIA_URL, document_root=django.conf.settings.MEDIA_ROOT)
Часть настроек:
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# URL that handles the media served from MEDIA_ROOT, used for managing stored files.
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / ''
Шаблон:
<section class="products section-padding">
<div class="container">
<div class="row">
{% for wine in page_obj %}
<div class="col-lg-4 col-12 mb-3">
<div class="product-thumb">
<a href="product-detail.html">
<img src="{{ MEDIA_URL }}{{ wine.image.url }}" class="img-fluid product-image" alt="">
</a>
<div class="product-info d-flex">
<div>
<h5 class="product-title mb-0">
<a href="product-detail.html" class="product-title-link">{{ wine.name }}</a>
</h5>
<p class="product-p">{{ wine.description }}</p>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</span>
</div>
Это не имеет никакого отношения к пагинации. Это просто означает, что есть Wine
объект, в котором изображение не ссылается на (существующий) файл изображения.
Сначала вы можете проверить, не является ли изображение None
:
{% if wine.image %}
<a href="product-detail.html">
<img src="{{ wine.image.url }}" class="img-fluid product-image" alt="image of the wine">
</a>
{% endif %}
Кроме того, вы должны убедиться, что содержимое ссылается на реальный файл, иначе мы получим 404 при обслуживании медиафайла.
Обычно MEDIA_ROOT
в шаблоне не нужен: .url
обычно сам добавляет медиа-префикс, если он настроен правильно.
Вы также можете отфильтровать Wine
без изображения:
def wines_page_red(request):
red_wines_list = Wine.objects.filter(type='Red', image__isnull=False)
paginator = Paginator(red_wines_list, 9)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'red-wines.html', {'page_obj': page_obj})