Django Pagination: Flexible Anzahl je Seite

Django, Flask, Bottle, WSGI, CGI…
Antworten
luvlinux
User
Beiträge: 33
Registriert: Donnerstag 24. August 2017, 08:53

Guten Abend,

ich habe mit Paginator eine Bootstrap Pagination erstellt, die soweit auch gut funktioniert (vgl. Screenshot https://ibb.co/kxfb88T). Allerdings würde ich gerne die Anzahl der angezeigten Datensätze (z. B. 10, 25, 50, 100) durch ein Selector-Feld variabel einstellen (vgl. obigen Screenshot). Ich habe auch schon bei stackoverflow einen Lösungsansatz (https://stackoverflow.com/questions/172 ... er-1730267) gefunden, der wie folgt aussieht:

Code: Alles auswählen

# Assuming you're reading the Query String value ?p=
try:
    per_page = int(request.REQUEST['p'])
except:
    per_page = 25     # default value
paginator = Paginator(objects, per_page)
Allerdings komme ich nicht damit klar, wie ich diesen in die views.py und index.html implementieren soll (liegt auch daran, dass ich den dort empfohlenen Request "per_page = int(request.REQUEST['p'])" nicht verstehe. Was auch noch ein Problem darstellt ist, dass sich der ausgewählte Wert im Selektor-Feld auf die Standardauswahl ändert, sobald man die Seite z. B. von Seite 2 auf 3 wechselt.

Könnt ihr mir hier vielleicht helfen wie genau ich meinen Code in der views.py bzw. index.html anpassen muss? Habt vielen Dank für eine Antwort.

Mein derzeitiger Code sieht wie folgt aus:

Code: Alles auswählen

views.py
...
def index(request):
    webpages = Webpage.objects.order_by('-id')
    paginator = Paginator(webpages, 5)
    page = request.GET.get('page')
    paged_webpages = paginator.get_page(page)
    return render(request, 'first_app/index.html', {'webpages': paged_webpages})

Code: Alles auswählen

urls.py
...
urlpatterns = [
    path('', views.index, name='index'),
]

Code: Alles auswählen

index.html:
...
  <!-- Paginator -->
  <div class="row">
    <div class="col-md-12">
      {% if webpages.has_other_pages %}
        <ul class="pagination">
          {% if webpages.has_previous %}
            <li class="page-item">
              <a href="?page={{ webpages.previous_page_number }}" class="page-link">&laquo;</a>
            </li>
          {% else %}
            <li class="page-item disabled">
              <a class="page-link">&laquo;</a>
            </li>
          {% endif %}
          {% for i in webpages.paginator.page_range %}
            {% if webpages.number == i %}
              <li class="page-item active">
                <a class="page-link">{{ i }}</a>
              </li>
            {% else %}
              <li class="page-item">
                <a href="?page={{ i }}" class="page-link">{{ i }}</a>
              </li>
            {% endif %}
          {% endfor %}
          {% if webpages.has_next %}
            <li class="page-item">
              <a href="?page={{ webpages.next_page_number }}" class="page-link">&raquo;</a>
            </li>
          {% else %}
            <li class="page-item disabled">
              <a class="page-link">&raquo;</a>
            </li>
          {% endif %}
        </ul>
      {% endif %}
    </div>
  </div>

  <select class="custom-select" id="selector">
    <option selected>Choose items per page</option>
    <option value="1">10</option>
    <option value="2">25</option>
    <option value="3">50</option>
  </select>
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Neben der `page` mußt Du halt auch den `item_count_per_page` als Parameter bei jeder `href` mit angeben. Um die Anzahl zu ändern, ohne Javascript zu brauchen, wäre es am einfachsten, das `select` auch durch Links zu ersetzen.
luvlinux
User
Beiträge: 33
Registriert: Donnerstag 24. August 2017, 08:53

Hallo Sirius3,
erstmals vielen Dank für deine Antwort, mit der ich schon einen Teil meines Problems lösen konnte - und zwar hab ich Folgendes gemacht:

Code: Alles auswählen

# Anpassung der views.py:

def index(request):
    webpages = Webpage.objects.order_by('-id')

    try:
        item_count_per_page = int(request.GET.get('p'))
    except:
        item_count_per_page = 5  # default value

    paginator = Paginator(webpages, item_count_per_page)
    page = request.GET.get('page')
    paged_webpages = paginator.get_page(page)
    return render(request, 'first_app/index.html', {'webpages': paged_webpages})
Desweiteren habe ich - um das Ganze zu testen - an all meine Paginator-Links ein p=3 angefügt:

Code: Alles auswählen

<a href="?page={{ webpages.previous_page_number }}&p=3" class="page-link">&laquo;</a>
Die Url sieht dann wie folgt aus:

Code: Alles auswählen

http://127.0.0.1:8000/?page=2&p=3
und es funktioniert auch alles soweit (vgl. Screenshot) https://ibb.co/NWdjYR3
Desweiteren habe ich das Select herausgenommen. Meine weitere Überlegung war dann drei Links mit den Werten 10, 15, 20 einzufügen (vgl. obigen Screenshot bzw. folgender Code:

Code: Alles auswählen

<h4>Number of items per page:
  <a href="">10</a>
  <a href="">15</a>
  <a href="">20</a>
</h4>
Allerdings ist mir nicht klar wie ich die Verbindung zu meinen Paginator-Links herstelle, wo ich ja die derzeit festcodierte 3 variabel machen muss. Das müsste ja dann irgendwie so aussehen:

Code: Alles auswählen

<a href="?page={{ i }}&p=value_of_clicked_link" class="page-link">{{ i }}</a>
Würdet ihr mir hier bitte nochmals helfen?
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

So wie Du jeden anderen Variable auch behandelst, Du übergibst sie der `render`-Methode.

Code: Alles auswählen

<a href="?page={{ webpages.previous_page_number }}&p={{item_count_per_page}}" class="page-link">&laquo;</a>
luvlinux
User
Beiträge: 33
Registriert: Donnerstag 24. August 2017, 08:53

@Sirius3
Ich glaube ich habe mich nicht richtig ausgedrückt, ich versuche es mal so:
Um eine bestimmte Anzahl der Datensätze je Seite auszuwählen, klicke ich doch auf einen der 3 Links

Code: Alles auswählen

<h4>Number of items per page:
  <a href="">10</a>
  <a href="">15</a>
  <a href="">20</a>
</h4>
also z. B. auf den ersten Link, um die Anzahl 10 auszuwählen, Dann sollte der Wert 10 doch an die Variable item_count_per_page übergeben werden.
Das sollte dann dazu führen, dass der Paginator-Link

Code: Alles auswählen

<a href="?page={{ webpages.previous_page_number }}&p={{item_count_per_page}}" class="page-link">&laquo;</a>
dann beim Klicken die Url:
http://127.0.0.1:8000/?page=2&p=&p=10
erzeugen sollte. Oder bringe ich da jetzt irgendwas durcheinander bzw. wie bekomme ich Django dazu die zuvor genannte Url zu erzeugen?
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Links sind wie die anderen auch:

Code: Alles auswählen

<h4>Number of items per page:
<a href="?page={{pagenumber_10}}&p=10" class="page-link">10</a>
<a href="?page={{pagenumber_15}}&p=15" class="page-link">15</a>
<a href="?page={{pagenumber_20}}&p=20" class="page-link">20</a>
Du mußt nur noch die richtige Seitenzahl berechnen, wenn man von einer Anzahl zur anderen wechselt.
luvlinux
User
Beiträge: 33
Registriert: Donnerstag 24. August 2017, 08:53

@Sirius3
Jetzt hat es geklappt bzw. es funktioniert soweit. Das mit der Berechnung der Seitenzahlen muss ich mir allerdings noch zu Gemüte führen :)

Vielen Dank für Deine hilfreiche Unterstützung!
Antworten