基于 Django Class 的分页视图无法正常工作

Pagination Django Class Based View Not Working Properly

我正在尝试将 Django (v2.0) 分页与 CBV 结合使用,但遇到了问题。分页是活动的,因为标签 {% if is_paginated %} returns "True" 并显示 "PagNav" 并且浏览器路径也发生变化,像这样 (..?page= 1, ...?page=2, etc...) 但是显示的元素都是,不是我在"paginate_by=3"中设置的3个。例如,如果查询有 15 个元素,则必须每页显示 3 个元素,在下面的分页中显示 1 到 5 个元素,但显示所有元素。我附上一张图片和代码:

models.py:

from django.db import models
from django.contrib.auth.models import User
from ckeditor.fields import RichTextField

# Create your models here.

class Project(models.Model):
    user = models.ForeignKey(User, on_delete = models.CASCADE, default=1)
    name = models.CharField(verbose_name='Nombre del proyecto', max_length=200)
    client = models.CharField(verbose_name='Nombre del cliente', max_length=200)
    description = RichTextField(verbose_name='Descripción')
    start = models.DateField(verbose_name='Fecha de Inicio', null=True, blank=True)
    ending = models.DateField(verbose_name='Fecha de Finalización', null=True, blank=True)
    order = models.SmallIntegerField(verbose_name="Orden", default=0)
    created = models.DateTimeField(verbose_name='Fecha de creación', auto_now_add=True)
    updated = models.DateTimeField(verbose_name='Fecha de modificación', auto_now=True)

    class Meta:
        verbose_name = 'Proyecto'
        verbose_name_plural = 'Proyectos'
        ordering = ['-start', 'order']

    def __str__(self):
        return self.name

class Album(models.Model):
    project = models.ForeignKey(Project, verbose_name='Proyecto relacionado', on_delete = models.CASCADE)
    title = models.CharField(verbose_name='Título de la imagen', max_length=200)
    image = models.ImageField(verbose_name='Imagen', upload_to='portfolio')
    created = models.DateTimeField(verbose_name='Fecha de creación', auto_now_add=True)
    updated = models.DateTimeField(verbose_name='Fecha de modificación', auto_now=True)

    class Meta:
        verbose_name = 'Imagen en el album'
        verbose_name_plural = 'Imágenes en el album'
        ordering = ['created']

        def __str__(self):
            return self.title

views.py:

@method_decorator(staff_member_required(login_url='login'), name='dispatch')
class AlbumListView(SingleObjectMixin, ListView):

    paginate_by = 3
    template_name = "core/album_list_form.html"


    def get(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Project.objects.all())
        return super().get(request, *args, **kwargs)


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['project'] = self.object
        return context


    def get_queryset(self):
        return self.object.album_set.all()


@method_decorator(staff_member_required(login_url='login'), name='dispatch')
class ProjectUpdateView(UpdateView):

    model = Project
    template_name = "core/project_update_form.html"
    form_class = ProjectUpdateForm


    def get_success_url(self):
        return  reverse_lazy('portfolio_update', args=[self.object.id]) + '?ok'

urls.py:

from django.urls import path
from . import views

from .views import *

urlpatterns = [
    path('', HomePageView.as_view(), name="home"),
    path('album/list/<int:pk>', AlbumListView.as_view(), name="portfolio_list_album"),
    # Update Views
    path('project/update/<int:pk>', ProjectUpdateView.as_view(), name="portfolio_update"),
    .
    .
    .

album_list_form.html:

{% extends "core/base.1.html" %}
{% load static %}
{% block title %}Imágenes de {{project.name}}{% endblock %}

{% block content %}

    <div class="container">
        <div class="row mt-5 mb-2 ml-1">
            <div class="mt-3">
                <h2 class="mt-5 mb-0"><a style="color: #343a40;" href="{% url 'portfolio_update' project.id %}">{{project.name}}</a></h2>
                <div class="subheading mb-5">Imágenes:</div>
            </div>
        </div>
    </div>


    <div class="album py-5 bg-light">
        <div class="container" style="margin-bottom: 2.5rem!important; margin-top: 2.5rem!important;">
            <div class="row">

                {% for album in project.album_set.all %}          

                        <div class="col-md-4">
                            <div class="card mb-4 shadow-sm">
                            <img class="card-img-top border-bottom p-2 p-2 p-2 p-2 bg-light" src="{{album.image.url}}" alt="Card image cap">
                            <div class="card-body">
                                <p class="card-text" title="{{album.title}}" style="color: #343a40;"><strong>{{album.title|truncatechars:31}}</strong></p>
                                <div class="d-flex justify-content-between align-items-center">
                                <div class="btn-group">
                                    <button type="button" class="btn btn-sm btn-outline-warning"><i class="fa fa fa-pencil"></i></button>
                                    <button type="button" class="btn btn-sm btn-outline-danger"><i class="fa fa fa-times"></i></button>    
                                </div>
                                <p></p>

                                </div>
                                <small class="text-muted">Última modificación: {{album.updated|date:"SHORT_DATE_FORMAT"}} {{album.updated|time:"h:i a"}}</small>
                            </div>
                            </div>
                        </div>           

                {% endfor %}
            </div>


        </div>

            {% if is_paginated %}

                <nav aria-label="Page navigation example">
                    <ul class="pagination pagination-lg justify-content-center">

                        {% if page_obj.has_previous %}
                            <li class="page-item">
                                <a class="page-link" style="color:#bd5d38;" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                    <span class="sr-only">Previous</span>
                                </a>
                            </li>
                        {% endif %}

                        {% for i in paginator.page_range %}
                            {% if page_obj.number == i %}
                                <li class="page-item"><a class="page-link" style="color:#ffffff; background-color: #343a40;" href="?page={{ i }}">{{ i }}</a></li>
                            {% else %}
                                <li class="page-item"><a class="page-link" style="color:#bd5d38;" href="?page={{ i }}">{{ i }}</a></li>
                            {% endif %}
                        {% endfor %}

                        {% if page_obj.has_next %}
                            <li class="page-item">
                                <a class="page-link" style="color:#bd5d38;" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                                <span class="sr-only">Next</span>
                                </a>
                            </li>
                        {% endif %}

                    </ul>
                </nav>

            {% endif %}

    </div>

{% endblock %}

我认为问题的核心是你在模板中写的:

{% for album in <b>project.album_set.all</b> %}

您因此创建了一个 project 对象。但是无论您是否对基于 class 的视图进行分页,您都不会对相关的对象管理器进行分页。您只对 object_list.

进行分页

也许你可以解决它:

{% for album in <b>object_list</b> %}

此外,我认为您使基于 class 的视图变得极其复杂:这是基于 class 的视图 Albums。是的,过滤 相册,但是 Album 应该是这里的中心。我觉得可以改写为:

from django.urls import path
from . import views

from .views import *

urlpatterns = [
  path('', HomePageView.as_view(), name="home"),
  path('album/list/<int:<b>project_pk</b>>', AlbumListView.as_view(), name="portfolio_list_album"),
  path('project/update/<int:pk>', ProjectUpdateView.as_view(), name="portfolio_update"),
]

然后在视图中:

@method_decorator(staff_member_required(login_url='login'), name='dispatch')
class AlbumListView(ListView):

    model = Album
    paginate_by = 3
    template_name = "core/album_list_form.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        <b>context['project'] = Project.objects.get(pk=self.kwargs['project_pk'])</b>
        return context

    def get_queryset(self):
        return <b>Album.objects.filter(project_id=self.kwargs['project_pk'])</b>