diff --git a/dashboard/mixins.py b/dashboard/mixins.py
index c28dcf8..3ebac58 100644
--- a/dashboard/mixins.py
+++ b/dashboard/mixins.py
@@ -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
diff --git a/dashboard/templates/unassigned_devices.html b/dashboard/templates/unassigned_devices.html
index c21a2be..cb8a42c 100644
--- a/dashboard/templates/unassigned_devices.html
+++ b/dashboard/templates/unassigned_devices.html
@@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load i18n %}
+{% load paginacion %}
+
{% block content %}
@@ -55,4 +57,9 @@
+
+
+ {% render_pagination page total_pages %}
+
+
{% endblock %}
diff --git a/dashboard/templatetags/__init__.py b/dashboard/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/dashboard/templatetags/paginacion.py b/dashboard/templatetags/paginacion.py
new file mode 100644
index 0000000..7a50113
--- /dev/null
+++ b/dashboard/templatetags/paginacion.py
@@ -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,
+ }
diff --git a/dashboard/templatetags/range.py b/dashboard/templatetags/range.py
new file mode 100644
index 0000000..7e4a724
--- /dev/null
+++ b/dashboard/templatetags/range.py
@@ -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
diff --git a/dashboard/views.py b/dashboard/views.py
index 79b9346..5384cc4 100644
--- a/dashboard/views.py
+++ b/dashboard/views.py
@@ -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()
diff --git a/device/models.py b/device/models.py
index f1b1ee7..6264130 100644
--- a/device/models.py
+++ b/device/models.py
@@ -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):
diff --git a/prevision.txt b/prevision.txt
deleted file mode 100644
index b1ad84d..0000000
--- a/prevision.txt
+++ /dev/null
@@ -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