'else' 子句中返回的对象的分页

Pagination for the objects returned in 'else' clause

我有以下模型,只有在我不按标签过滤时分页才能正常工作。一旦我按标签过滤广告,分页就不起作用了。

class AdListView(ListView):
paginate_by = 2
model = Ad
context_object_name = 'ads'

def get_context_data(self, **kwargs):
    if self.request.GET.get('tags') is None:
        context = super().get_context_data(**kwargs)
        context.update(tags=Tag.objects.all())
        return context
    else:
        tag_submitted = Tag.objects.get(name=self.request.GET.get('tags'))
        ads_by_tag = tag_submitted.related_ads.all()
        context = {
            'ads': ads_by_tag
        }
        context.update(tags=Tag.objects.all())
        return context

需要做些什么才能使分页适用于带过滤器和不带过滤器的两种情况?

下面是models.py和模板

models.py

class Tag(BaseModel):

def __str__(self):
    return str(self.name)


class Ad(BaseModel):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=500)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
    date_created = models.DateField(auto_now_add=True)
    date_modified = models.DateField(auto_now=True)
    tags = models.ManyToManyField(Tag, related_name='related_ads')
    price = models.PositiveIntegerField(default=0)
    archived = models.BooleanField(default=False)

    def __str__(self):
         return str(self.name)

    class Meta:
         ordering = ['-date_created']

模板

{% block content %}
<div class="container">
    <div class="row">
        <div class="w-75">
            <table class="table">
                <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">Title</th>
                </tr>
                </thead>
                <tbody>
                {% for ad in ads %}
                    <tr>
                        <td>{{ forloop.counter }}</td>
                        <td><a href="{% url 'ads-detail' ad.id %}"> {{ ad.name }} </a></td>
                    </tr>
                {% empty %}
                    <li>No ads yet.</li>
                {% endfor %}
                </tbody>
            </table>
        </div>
        <div class="w-25">
            <table class="table">
                <thead>
                <tr>
                    <th scope="col">Tags</th>
                </tr>
                </thead>
                <tbody>
                {% for tag in tags %}
                    <tr>
                        <td><a href="{% url 'ads-list'%}?tags={{ tag }}"> {{ tag }} </a></td>
                    </tr>
                {% empty %}
                    <li>No tags yet.</li>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
    <div class="row">
        <div class="pagination">
        <span class="step-links">
            {% if page_obj.has_previous %}
                <a href="?page=1">&laquo; 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 &raquo;</a>
            {% endif %}
        </span>
        </div>
    </div>
</div>
{% endblock %}

所以这是一个学习django的项目,所以也欢迎任何其他关于如何改进代码的评论。

您应该.get_context_data() [Django-doc]. In Django you pass the (possibly) filtered queryset in .get_queryset(…) [Django-doc]中过滤。然后 Django 将对查询集进行分页,并将其添加到上下文中。通过覆盖上下文中的项目,您现在已经删除了分页查询集,并添加了一个过滤查询集。

因此您提供过滤后的查询集,让 Django 进行适当的分页:

class AdListView(ListView):
    paginate_by = 2
    model = Ad
    context_object_name = 'ads'

    def get_search_querystring(self):
        copy = self.request.GET.copy()
        copy.pop(self.page_kwarg, None)
        return copy.urlencode()

    def <strong>get_queryset</strong>(self, *args, **kwargs):
        qs = super().get_queryset(*args, **kwargs)
        if 'tags' in self.request.GET:
            return qs.filter(tags__name=self.request.GET['tags'])
        return qs

    def get_context_data(*args, **kwargs):
        return super().get_context_data(*args<strong>, tags=Tag.objects.all()</strong>, **kwargs)

另一个问题是模板中的 link:通过使用 ?page={{ page_obj.next_page_number }},这将“删除”包含搜索查询的 query string [wiki],并且只使用 page 作为查询字符串中的 only 变量。

因此在模板中我们可以使用 URL 作为:

<a href="?page={{ page_obj.next_page_number }}&{{ view.get_search_queryset|safe }}">

其他分页 links 也应该发生同样的情况。