Django проблема с разбивкой на страницы - страницы не разбиваются на страницы - PullRequest
0 голосов
/ 07 мая 2020

Я использую Django -фильтры для фильтрации результатов. Фильтр работает правильно, но теперь разбивка на страницы не работает. Он отображается, но теперь все товары отображаются на одной странице. Я использовал paginate_by = 6, так как это представление на основе классов . Даже после результатов фильтрации, например, есть 8 продуктов, соответствующих фильтру, все отображается на одной странице. Почему не работает? Кто-нибудь может мне помочь? Заранее спасибо!

My filters.py:

import django_filters
from .models import Item

class ItemFilter(django_filters.FilterSet):

    class Meta:
        model = Item

        fields = {
            'category': ['exact'],
            'price': ['lte']
        }

My views.py:

from .filters import ItemFilter

class homeview(ListView):
    model = Item
    template_name = 'products/home.html'
    paginate_by = 6


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = ItemFilter(self.request.GET, queryset=self.get_queryset())
        return context

My index. html:

<div class="card mb-4">
  <div class="card-body">
    <div class="container">
      <form method="GET">
        {{ filter.form|crispy }}
          <button type="submit" class="btn btn-primary mt-4">Filter</button>
      </form>
    </div>
  </div>
</div>

<h1>List Of Items</h1>
  <div class="row mb-4">
    {% for item in filter.qs %}
      <div class="col-lg-4">
        <img class="thumbnail" src="{{ item.image_url }}">
          <div class="box-element product">
            <h6><strong>{{ item.title }}</strong></h6>
            <h6 class="text-success">Category - {{ item.get_category_display }}</h6>
            <hr>
          </div>
      </div> 
    {% endfor %}
  </div>


<ul class="pagination justify-content-center">
          {% if is_paginated %}

            {% if page_obj.has_previous %}
              <a class="btn btn-outline-dark mb-4" href="?page=1">First</a>
              <a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
            {% endif %}

            {% for num in page_obj.paginator.page_range %}
              {% if page_obj.number == num %}
                <a class="btn btn-dark mb-4" href="?page={{ num }}">{{ num }}</a>
              {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
                <a class="btn btn-outline-dark mb-4" href="?page={{ num }}">{{ num }}</a>
              {% endif %}
            {% endfor %}

            {% if page_obj.has_next %}
              <a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
              <a class="btn btn-outline-dark mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
            {% endif %}

          {% endif %}
        </ul>

Ответы [ 3 ]

1 голос
/ 16 мая 2020

Прежде всего, вы не используете объект страницы, созданный методами ListView django. Технически вместо этого вы передаете новый набор запросов. Поэтому вы перечисляете все результаты вместо результатов, разбитых на страницы.

super (). Context уже имеет объект страницы, который здесь не используется. поскольку вы используете ItemFilter

Вот как я справлюсь с ситуацией. без django_filters, хотя

forms.py

class FilterForm(forms.Form):
    category = forms.CharField()
    price = forms.IntegerField()

views.py

from .forms.py import FilterForm
class HomeView(ListView):

    model = Item
    template_name = 'products/home.html'
    paginate_by = 6

    def get_filter_args(self):
        request = self.request
        filter_args = {}
        filter_args['category'] = request.GET.get('category')
        filter_args['price__lte'] = request.GET.get('price')

        # To remove filter arg if the value is null. to avoid errors
        filter_args = {key: value for key, value in filter_args.items() if value}

        return filter_args

    def get_queryset(self):
        filter_args = self.get_filter_args()
        queryset = super().get_queryset().filter(**filter_args)

        return queryset

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

Чтобы предотвратить потерю применяемых фильтров при разбиении на страницы, используйте помощник для сборки url для разбивки на страницы добавьте этот файл в папку templatetags внутри папки приложения (тот же путь, где и views.py, models.py et c ...)

temptag.py

register = template.Library()

@register.simple_tag    
def paginate_url(field_name, value, urlencode=None):
    get_query = f'{field_name}={value}'
    if urlencode:
        qs = urlencode.split('&')
        _filtered = filter(lambda p: p.split('=')[0] != field_name, qs)
        querystring = '&'.join(_filtered)
        get_query = f'{get_query}&{querystring}'
    return get_query

вы можете импортировать помощник шаблона внутри html файл html файл

{% load temptag %}
<div class="card mb-4">
  <div class="card-body">
    <div class="container">
      <form method="GET">
        {{ form|crispy }}
          <button type="submit" class="btn btn-primary mt-4">Filter</button>
      </form>
    </div>
  </div>
</div>

<h1>List Of Items</h1>
  <div class="row mb-4">
    {% for item in object_list %}
      <div class="col-lg-4">
        <img class="thumbnail" src="{{ item.image_url }}">
          <div class="box-element product">
            <h6><strong>{{ item.title }}</strong></h6>
            <h6 class="text-success">Category - {{ item.get_category_display }}</h6>
            <hr>
          </div>
      </div> 
    {% endfor %}
  </div>


<ul class="pagination justify-content-center">
          {% if is_paginated %}

            {% if page_obj.has_previous %}
              <a class="btn btn-outline-dark mb-4" href="?{% paginate_url 'page' 1 request.GET.urlencode %}">First</a>
              <a class="btn btn-outline-dark mb-4" href="?{% paginate_url 'page' page_obj.previous_page_number request.GET.urlencode %}">Previous</a>
            {% endif %}

        {% for num in page_obj.paginator.page_range %}
          {% if page_obj.number == num %}
            <a class="btn btn-dark mb-4" href="?{% paginate_url 'page' num request.GET.urlencode %}">{{ num }}</a>
          {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
            <a class="btn btn-outline-dark mb-4" href="?{% paginate_url 'page' num request.GET.urlencode %}"</a>
          {% endif %}
        {% endfor %}

        {% if page_obj.has_next %}
          <a class="btn btn-outline-dark mb-4" href="?{% paginate_url 'page' page_obj.next_page_number request.GET.urlencode %}">Next</a>
          <a class="btn btn-outline-dark mb-4" href="?{% paginate_url 'page' page_obj.paginator.num_pages request.GET.urlencode %}">Last</a>
        {% endif %}

      {% endif %}
    </ul>
0 голосов
/ 17 мая 2020

У меня была аналогичная проблема при использовании django -фильтра. Однако в моем решении использовался список . js, так как у меня была таблица, которую я не только хочу разбить на страницы, но я хотел, чтобы заголовки таблиц можно было сортировать.

Вероятно, вы можете использовать List. js здесь, даже если у вас нет списка или таблицы данных (вы также можете проверить пример кода создателя List. js).

index. html:

<h1>List Of Items</h1>
  <div id="paginate-items"> <!-- Need a container with a unique ID for List.js -->
    <div class="row mb-4 list"> <!-- Must include the class "list" for the div containing the data to be paginated -->
      {% for item in filter.qs %}
        <div class="col-lg-4">
          <img class="thumbnail" src="{{ item.image_url }}">
            <div class="box-element product">
              <h6><strong>{{ item.title }}</strong></h6>
              <h6 class="text-success">Category - {{ item.get_category_display }}</h6>
              <hr>
            </div>
        </div> 
      {% endfor %}
    </div>
    <ul class="pagination"></ul>
  </div>
  ...
  <!-- You'll need to include jQuery and List.js just before the close of the '<body>' tag: -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js"></script>

Затем в отдельном. js файле:

var myData= new List('paginate-items', {
  page: 3, // refers to how many items per page
  pagination: true
});

И некоторые простые стили в отдельном. css файле:

.pagination li {
  display:inline-block;
  padding:5px;
}
0 голосов
/ 07 мая 2020

Напишите свой get_context_data () вот так

def get_context_data(self, **kwargs):
    items = Item.objects.all()
    context = super().get_context_data(**kwargs)
    context['filter'] = ItemFilter(self.request.GET, queryset=items)
    return context
...