diff options
author | Johannes Löthberg <johannes@kyriasis.com> | 2018-01-02 19:08:10 +0100 |
---|---|---|
committer | Angel Velásquez <angvp@archlinux.org> | 2018-01-02 13:08:10 -0500 |
commit | 5538aa8799788e19a1691bd3c2e889bb088e654b (patch) | |
tree | 3cc45ae812a8a3d576fe04952a3d0eeba06f8fd7 /packages | |
parent | 860a0511a0b465222b45ae3e19b20d07165651fe (diff) | |
download | archweb-5538aa8799788e19a1691bd3c2e889bb088e654b.tar.gz archweb-5538aa8799788e19a1691bd3c2e889bb088e654b.zip |
Add pagination to JSON package search (#73)release_2018-01-02
* Add pagination to JSON search form using Paginator
The downside of this is that we can't easily run prefetch_related
anymore, but given the limit I don't suspect this to be a problem.
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
* packages/views/search: Add appropriate newlines to search_json
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
* Update package fixture to be the same as devel/fixtures/core.db.tar.gz
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
* packages/tests: Add tests for JSON search pagination
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
Diffstat (limited to 'packages')
-rw-r--r-- | packages/tests.py | 30 | ||||
-rw-r--r-- | packages/views/search.py | 25 |
2 files changed, 46 insertions, 9 deletions
diff --git a/packages/tests.py b/packages/tests.py index 69bf2e76..5c70aaf4 100644 --- a/packages/tests.py +++ b/packages/tests.py @@ -75,8 +75,9 @@ class PackageSearchJson(TestCase): response = self.client.get('/packages/search/json/?repository=core') self.assertEqual(response.status_code, 200) data = json.loads(response.content) - self.assertEqual(len(data['results']), 1) - self.assertEqual(data['results'][0]['pkgname'], 'linux') + self.assertEqual(len(data['results']), 5) + self.assertEqual(set(map(lambda r: r['pkgname'], data['results'])), + {"coreutils", "glibc", "linux", "pacman", "systemd"}) def test_packagename(self): response = self.client.get('/packages/search/json/?name=linux') @@ -90,6 +91,23 @@ class PackageSearchJson(TestCase): data = json.loads(response.content) self.assertEqual(len(data['results']), 0) + def test_limit_four(self): + response = self.client.get('/packages/search/json/?limit=4') + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['page'], 1) + self.assertEqual(data['num_pages'], 2) + self.assertEqual(data['limit'], 4) + self.assertEqual(len(data['results']), 4) + + def test_second_page(self): + response = self.client.get('/packages/search/json/?limit=4&page=2') + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['page'], 2) + self.assertEqual(data['num_pages'], 2) + self.assertEqual(len(data['results']), 1) + class PackageSearch(TestCase): fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', @@ -113,7 +131,7 @@ class PackageSearch(TestCase): def test_filter_repo(self): response = self.client.get('/packages/?repo=Core') self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content) + self.assertIn('5 matching packages found', response.content) def test_filter_desc(self): response = self.client.get('/packages/?desc=kernel') @@ -128,7 +146,7 @@ class PackageSearch(TestCase): def test_filter_not_flagged(self): response = self.client.get('/packages/?flagged=Not Flagged') self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content) + self.assertIn('5 matching packages found', response.content) def test_filter_arch(self): response = self.client.get('/packages/?arch=any') @@ -138,11 +156,11 @@ class PackageSearch(TestCase): def test_filter_maintainer_orphan(self): response = self.client.get('/packages/?maintainer=orphan') self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content) + self.assertIn('5 matching packages found', response.content) def test_filter_packager_unknown(self): response = self.client.get('/packages/?packager=unknown') self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content) + self.assertIn('5 matching packages found', response.content) # vim: set ts=4 sw=4 et: diff --git a/packages/views/search.py b/packages/views/search.py index 6e892251..264e7bf6 100644 --- a/packages/views/search.py +++ b/packages/views/search.py @@ -1,6 +1,7 @@ import json from django import forms +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.contrib.auth.models import User from django.db.models import Q from django.http import HttpResponse @@ -14,6 +15,8 @@ from ..utils import attach_maintainers, PackageJSONEncoder class PackageSearchForm(forms.Form): + limit = forms.CharField(required=False) + page = forms.CharField(required=False) repo = forms.MultipleChoiceField(required=False) arch = forms.MultipleChoiceField(required=False) name = forms.CharField(required=False) @@ -155,13 +158,29 @@ def search_json(request): form = PackageSearchForm(data=request.GET, show_staging=request.user.is_authenticated()) if form.is_valid(): + form_limit = form.cleaned_data['limit'] + limit = min(limit, int(form_limit)) if form_limit else limit + container['limit'] = limit + packages = Package.objects.select_related('arch', 'repo', 'packager') if not request.user.is_authenticated(): packages = packages.filter(repo__staging=False) - packages = parse_form(form, packages)[:limit] - packages = packages.prefetch_related('groups', 'licenses', - 'conflicts', 'provides', 'replaces', 'depends') + packages = parse_form(form, packages) + + paginator = Paginator(packages, limit) + container['num_pages'] = paginator.num_pages + + page = form.cleaned_data.get('page') + page = int(page) if page else 1 + container['page'] = page + try: + packages = paginator.page(page) + except PageNotAnInteger: + packages = paginator.page(1) + except EmptyPage: + packages = paginator.page(paginator.num_pages) + attach_maintainers(packages) container['results'] = packages container['valid'] = True |