Pagination for list of devices in dashboard and lots

This commit is contained in:
Cayo Puigdefabregas 2024-10-02 12:13:05 +02:00
parent 6399739228
commit aa31aefb42
8 changed files with 121 additions and 49 deletions

View file

@ -1,5 +1,5 @@
from django.urls import resolve
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, Http404
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import LoginRequiredMixin
@ -44,7 +44,6 @@ class DashboardView(LoginRequiredMixin):
return context
def get_session_devices(self):
# import pdb; pdb.set_trace()
dev_ids = self.request.session.pop("devices", [])
self._devices = []
@ -82,3 +81,28 @@ class InventaryMixin(DashboardView, TemplateView):
except Exception:
pass
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
limit = self.request.GET.get("limit", 10)
page = self.request.GET.get("page", 1)
if limit:
try:
limit = int(limit)
page = int(page)
except:
raise Http404
offset = (page - 1) * limit
devices, count = self.get_devices(self.request.user, offset, limit)
total_pages = (count + limit - 1) // limit
context.update({
'devices': devices,
'count': count,
"limit": limit,
"offset": offset,
"page": page,
"total_pages": total_pages,
})
return context

View file

@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load i18n %}
{% load paginacion %}
{% block content %}
<div class="row">
@ -55,4 +57,9 @@
<button type="submit" value="{% url 'lot:del_devices' %}" name="url">Remove</button> <button type="submit" name="url" value="{% url 'lot:add_devices' %}">add</button>
</form>
</div>
<div class="row mt-3">
<div class="col">
{% render_pagination page total_pages %}
</div>
</div>
{% endblock %}

View file

View file

@ -0,0 +1,19 @@
from django import template
register = template.Library()
@register.inclusion_tag('pagination.html')
def render_pagination(page_number, total_pages):
"""
Template tag for render pagination
Args:
- page_number: number of actual page
- total_pages: total pages.
Use it template: {% render_pagination page_number total_pages %}
"""
return {
'page_number': page_number,
'total_pages': total_pages,
}

View file

@ -0,0 +1,23 @@
from django import template
register = template.Library()
@register.filter
def range_filter(value, page):
m = 11
mind = page -1 - m // 2
maxd = page + 1 + m // 2
if mind < 0:
maxd += abs(mind)
if maxd > value:
mind -= abs(maxd-value-1)
total_pages = [x for x in range(1, value + 1) if maxd > x > mind]
if value > m:
if total_pages[0] > 1:
total_pages = ["..."] + total_pages
if total_pages[-1] < value:
total_pages = total_pages + ["..."]
return total_pages

View file

@ -1,4 +1,6 @@
from django.utils.translation import gettext_lazy as _
from django.shortcuts import Http404
from dashboard.mixins import InventaryMixin, DetailsMixin
from device.models import Device
from lot.models import Lot
@ -10,15 +12,8 @@ class UnassignedDevicesView(InventaryMixin):
title = _("Unassigned Devices")
breadcrumb = "Devices / Unassigned Devices"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
devices = Device.get_unassigned(self.request.user)
context.update({
'devices': devices,
})
return context
def get_devices(self, user, offset, limit):
return Device.get_unassigned(self.request.user, offset, limit)
class LotDashboardView(InventaryMixin, DetailsMixin):
@ -30,14 +25,12 @@ class LotDashboardView(InventaryMixin, DetailsMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
devices = self.get_devices()
lot = context.get('object')
context.update({
'devices': devices,
'lot': lot,
})
return context
def get_devices(self):
def get_devices(self, user, offset, limit):
chids = self.object.devicelot_set.all().values_list("device_id", flat=True).distinct()
return [Device(id=x) for x in chids]
return [Device(id=x) for x in chids], chids.count()

View file

@ -1,4 +1,4 @@
from django.db import models
from django.db import models, connection
from utils.constants import STR_SM_SIZE, STR_SIZE, STR_EXTEND_SIZE, ALGOS
from evidence.models import Annotation, Evidence
@ -113,17 +113,46 @@ class Device:
self.lots = [x.lot for x in DeviceLot.objects.filter(device_id=self.id)]
@classmethod
def get_unassigned(cls, user):
chids = DeviceLot.objects.filter(lot__owner=user).values_list("device_id", flat=True).distinct()
annotations = Annotation.objects.filter(
owner=user,
type=Annotation.Type.SYSTEM,
).exclude(value__in=chids).values_list("value", flat=True).distinct()
return [cls(id=x) for x in annotations]
def get_unassigned(cls, user, offset=0, limit=None):
# return cls.objects.filter(
# owner=user
# ).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
sql = """
SELECT DISTINCT t1.value from evidence_annotation as t1
left join lot_devicelot as t2 on t1.value = t2.device_id
where t2.device_id is null and owner_id=={user} and type=={type}
""".format(
user=user.id,
type=Annotation.Type.SYSTEM,
)
if limit:
sql += " limit {} offset {}".format(int(limit), int(offset))
sql += ";"
annotations = []
with connection.cursor() as cursor:
cursor.execute(sql)
annotations = cursor.fetchall()
devices = [cls(id=x[0]) for x in annotations]
count = cls.get_unassigned_count(user)
return devices, count
@classmethod
def get_unassigned_count(cls, user):
sql = """
SELECT count(DISTINCT t1.value) from evidence_annotation as t1
left join lot_devicelot as t2 on t1.value = t2.device_id
where t2.device_id is null and owner_id=={user} and type=={type};
""".format(
user=user.id,
type=Annotation.Type.SYSTEM,
)
with connection.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()[0][0]
@property
def is_websnapshot(self):

View file

@ -1,23 +0,0 @@
4 login
8 device models
4 inventory template
4 upload snapshots
16 parse snapshots
16 build devices
8 action models
8 view actions
8 lot models
16 view lots
8 edit device
16 documents
8 tag
8 print label
4 server erase
4 profile
8 erase views
8 erase certificate
4 inventory snapshots
8 search
join split devices
168 horas => 21 dias