feat: paginate exchange rates

This commit is contained in:
Herculino Trotta
2024-11-30 02:18:02 -03:00
parent da10f461a6
commit 28096cd490
5 changed files with 99 additions and 18 deletions
-5
View File
@@ -23,11 +23,6 @@ urlpatterns = [
views.exchange_rates_list_pair, views.exchange_rates_list_pair,
name="exchange_rates_list_pair", name="exchange_rates_list_pair",
), ),
path(
"exchange-rates/pair/<str:from_currency>/<str:to_currency>",
views.exchange_rates_list_pair,
name="exchange_rates_list_pair",
),
path("exchange-rates/add/", views.exchange_rate_add, name="exchange_rate_add"), path("exchange-rates/add/", views.exchange_rate_add, name="exchange_rate_add"),
path( path(
"exchange-rates/<int:pk>/edit/", "exchange-rates/<int:pk>/edit/",
+11 -1
View File
@@ -1,5 +1,6 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import F, CharField, Value from django.db.models import F, CharField, Value
from django.db.models.functions import Concat from django.db.models.functions import Concat
from django.http import HttpResponse from django.http import HttpResponse
@@ -50,7 +51,10 @@ def exchange_rates_list(request):
@only_htmx @only_htmx
@login_required @login_required
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def exchange_rates_list_pair(request, from_currency=None, to_currency=None): def exchange_rates_list_pair(request):
from_currency = request.GET.get("from")
to_currency = request.GET.get("to")
if from_currency and to_currency: if from_currency and to_currency:
exchange_rates = ExchangeRate.objects.filter( exchange_rates = ExchangeRate.objects.filter(
from_currency__code=from_currency, to_currency__code=to_currency from_currency__code=from_currency, to_currency__code=to_currency
@@ -58,11 +62,17 @@ def exchange_rates_list_pair(request, from_currency=None, to_currency=None):
else: else:
exchange_rates = ExchangeRate.objects.all().order_by("-date") exchange_rates = ExchangeRate.objects.all().order_by("-date")
page_number = request.GET.get("page", 1)
paginator = Paginator(exchange_rates, 100)
page_obj = paginator.get_page(page_number)
return render( return render(
request, request,
"exchange_rates/fragments/table.html", "exchange_rates/fragments/table.html",
{ {
"exchange_rates": exchange_rates, "exchange_rates": exchange_rates,
"paginator": paginator,
"page_obj": page_obj,
"from_currency": from_currency, "from_currency": from_currency,
"to_currency": to_currency, "to_currency": to_currency,
}, },
@@ -27,7 +27,8 @@
{% for pair in pairings %} {% for pair in pairings %}
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">
<button class="nav-link" hx-indicator="#exchange-rates-table" <button class="nav-link" hx-indicator="#exchange-rates-table"
hx-get="{% url 'exchange_rates_list_pair' from_currency=pair.1 to_currency=pair.2 %}" hx-get="{% url 'exchange_rates_list_pair' %}"
hx-vals='{"from": "{{ pair.1 }}", "to": "{{ pair.2 }}"}'
hx-target="#exchange-rates-table" data-bs-toggle="tab" type="button" role="tab" hx-target="#exchange-rates-table" data-bs-toggle="tab" type="button" role="tab"
aria-controls="#exchange-rates-table" aria-selected="false">{{ pair.0 }}</button> aria-controls="#exchange-rates-table" aria-selected="false">{{ pair.0 }}</button>
</li> </li>
@@ -1,11 +1,7 @@
{% load currency_display %} {% load currency_display %}
{% load i18n %} {% load i18n %}
{% if from_currency and to_currency %} <div class="card-body show-loading" hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="updated from:window" hx-swap="outerHTML" hx-vals='{"page": "{{ page_obj.number }}", "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'>
<div class="card-body show-loading" hx-get="{% url 'exchange_rates_list_pair' from_currency=from_currency to_currency=to_currency %}" hx-trigger="updated from:window" hx-swap="outerHTML"> {% if page_obj %}
{% else %}
<div class="card-body show-loading" hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="updated from:window" hx-swap="outerHTML">
{% endif %}
{% if exchange_rates %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover text-nowrap"> <table class="table table-hover text-nowrap">
<thead> <thead>
@@ -17,7 +13,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for exchange_rate in exchange_rates %} {% for exchange_rate in page_obj %}
<tr class="exchange-rate"> <tr class="exchange-rate">
<td class="col-auto"> <td class="col-auto">
<div class="btn-group" role="group" aria-label="{% translate 'Actions' %}"> <div class="btn-group" role="group" aria-label="{% translate 'Actions' %}">
@@ -43,9 +39,9 @@
_="install prompt_swal"><i class="fa-solid fa-trash fa-fw"></i></a> _="install prompt_swal"><i class="fa-solid fa-trash fa-fw"></i></a>
</div> </div>
</td> </td>
<td class="col">{{ exchange_rate.date|date:"SHORT_DATETIME_FORMAT" }}</td> <td class="col-3">{{ exchange_rate.date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="col"><span class="badge rounded-pill text-bg-secondary">{{ exchange_rate.from_currency.code }}</span> x <span class="badge rounded-pill text-bg-secondary">{{ exchange_rate.to_currency.code }}</span></td> <td class="col-3"><span class="badge rounded-pill text-bg-secondary">{{ exchange_rate.from_currency.code }}</span> x <span class="badge rounded-pill text-bg-secondary">{{ exchange_rate.to_currency.code }}</span></td>
<td class="col">1 {{ exchange_rate.from_currency.code }} ≅ {% currency_display amount=exchange_rate.rate prefix=exchange_rate.to_currency.prefix suffix=exchange_rate.to_currency.suffix decimal_places=exchange_rate.to_currency.decimal_places%}</td> <td class="col-3">1 {{ exchange_rate.from_currency.code }} ≅ {% currency_display amount=exchange_rate.rate prefix=exchange_rate.to_currency.prefix suffix=exchange_rate.to_currency.suffix decimal_places=exchange_rate.to_currency.decimal_places%}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@@ -54,4 +50,83 @@
{% else %} {% else %}
<c-msg.empty title="{% translate "No exchange rates" %}" :remove-padding="True"></c-msg.empty> <c-msg.empty title="{% translate "No exchange rates" %}" :remove-padding="True"></c-msg.empty>
{% endif %} {% endif %}
{% if page_obj.has_other_pages %}
<div class="mt-auto">
<input value="{{ page_obj.number }}" name="page" type="hidden" id="page">
<nav aria-label="{% translate 'Page navigation' %}">
<ul class="pagination justify-content-center mt-5">
<li class="page-item">
<a class="page-link tw-cursor-pointer {% if not page_obj.has_previous %}disabled{% endif %}"
hx-get="{% if page_obj.has_previous %}{% url 'exchange_rates_list_pair' %}{% endif %}"
hx-vals='{"page": 1, "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'
hx-include="#filter, #order"
hx-target="#exchange-rates-table"
aria-label="Primeira página"
hx-swap="show:top">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% for page_number in page_obj.paginator.page_range %}
{% comment %}
This conditional allows us to display up to 3 pages before and after the current page
If you decide to remove this conditional, all the pages will be displayed
You can change the 3 to any number you want e.g
To display only 5 pagination items, change the 3 to 2 (2 before and 2 after the current page)
{% endcomment %}
{% if page_number <= page_obj.number|add:3 and page_number >= page_obj.number|add:-3 %}
{% if page_obj.number == page_number %}
<li class="page-item active">
<a class="page-link tw-cursor-pointer">
{{ page_number }}
</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link tw-cursor-pointer"
hx-get="{% url 'exchange_rates_list_pair' %}"
hx-vals='{"page": {{ page_number }}, "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'
hx-target="#exchange-rates-table"
hx-swap="show:top">
{{ page_number }}
</a>
</li>
{% endif %}
{% endif %}
{% endfor %}
{% if page_obj.number|add:3 < page_obj.paginator.num_pages %}
<li class="page-item">
<a class="page-link disabled"
aria-label="...">
<span aria-hidden="true">...</span>
</a>
</li>
<li class="page-item">
<a class="page-link tw-cursor-pointer"
hx-get="{% url 'exchange_rates_list_pair' %}" hx-target="#exchange-rates-table"
hx-vals='{"page": {{ page_obj.paginator.num_pages }}, "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'
hx-include="#filter, #order"
hx-swap="show:top"
aria-label="Última página">
<span aria-hidden="true">{{ page_obj.paginator.num_pages }}</span>
</a>
</li>
{% endif %}
<li class="page-item">
<a class="page-link {% if not page_obj.has_next %}disabled{% endif %} tw-cursor-pointer"
hx-get="{% if page_obj.has_next %}{% url 'exchange_rates_list_pair' %}{% endif %}"
hx-vals='{"page": {{ page_obj.paginator.num_pages }}, "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'
hx-include="#filter, #order"
hx-swap="show:top"
hx-target="#exchange-rates-table"
aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
{% endif %}
</div> </div>
@@ -4,5 +4,5 @@
{% block title %}{% translate 'Exchange Rates' %}{% endblock %} {% block title %}{% translate 'Exchange Rates' %}{% endblock %}
{% block content %} {% block content %}
<div hx-get="{% url 'exchange_rates_list' %}" hx-trigger="load, updated from:window" class="show-loading"></div> <div hx-get="{% url 'exchange_rates_list' %}" hx-trigger="load" class="show-loading"></div>
{% endblock %} {% endblock %}