From 6a429a8d898d5f0789f5b5a3f2858c6578fa5227 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 7 Mar 2011 21:50:13 -0600 Subject: Clean up current_query and preserve multiple args When implementing search for multiple architectures or repositories, I didn't update this method to accomidate the new query parameters. Clean it up a bit by not appending/stripping the leading '?' anywhere but in the template itself, and ensure we can handle multiple of any parameter passed in. Fixes FS#23180. Signed-off-by: Dan McGee --- packages/templatetags/package_extras.py | 16 +++++++++------- packages/views.py | 10 +++++----- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'packages') diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py index d59a5562..24264af0 100644 --- a/packages/templatetags/package_extras.py +++ b/packages/templatetags/package_extras.py @@ -1,4 +1,6 @@ -import cgi, urllib +import urllib +import urlparse + from django import template from django.utils.html import escape @@ -9,15 +11,15 @@ class BuildQueryStringNode(template.Node): self.sortfield = sortfield def render(self, context): - qs = dict(cgi.parse_qsl(context['current_query'][1:])) - if qs.has_key('sort') and qs['sort'] == self.sortfield: + qs = urlparse.parse_qs(context['current_query']) + if qs.has_key('sort') and self.sortfield in qs['sort']: if self.sortfield.startswith('-'): - qs['sort'] = self.sortfield[1:] + qs['sort'] = [self.sortfield[1:]] else: - qs['sort'] = '-' + self.sortfield + qs['sort'] = ['-' + self.sortfield] else: - qs['sort'] = self.sortfield - return '?' + urllib.urlencode(qs) + qs['sort'] = [self.sortfield] + return urllib.urlencode(qs, True) @register.tag(name='buildsortqs') def do_buildsortqs(parser, token): diff --git a/packages/views.py b/packages/views.py index 59779fe4..3cef8226 100644 --- a/packages/views.py +++ b/packages/views.py @@ -168,12 +168,10 @@ class PackageSearchForm(forms.Form): [(m.username, m.get_full_name()) for m in maints] def search(request, page=None): - current_query = '?' limit = 50 packages = Package.objects.select_related('arch', 'repo') if request.GET: - current_query += request.GET.urlencode() form = PackageSearchForm(data=request.GET) if form.is_valid(): if form.cleaned_data['repo']: @@ -208,12 +206,14 @@ def search(request, page=None): else: form = PackageSearchForm() - page_dict = {'search_form': form, - 'current_query': current_query - } if packages.count() == 1: return redirect(packages[0]) + current_query = request.GET.urlencode() + page_dict = { + 'search_form': form, + 'current_query': current_query + } allowed_sort = ["arch", "repo", "pkgname", "last_update", "flag_date"] allowed_sort += ["-" + s for s in allowed_sort] sort = request.GET.get('sort', None) -- cgit v1.2.3-2-g168b From 9730be60a8ef4a04358b0a026ce6b706de21d4e8 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 13 Mar 2011 11:29:05 -0500 Subject: Add package epoch support This comes with pacman 3.5, replacing the old "force" PKGBUILD option. We parse it and store it for now, but don't display it anywhere just yet. Also update a few queries relying on version differences in any of the multiple parts. Signed-off-by: Dan McGee --- packages/utils.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages') diff --git a/packages/utils.py b/packages/utils.py index 8d9f13ab..29a3087f 100644 --- a/packages/utils.py +++ b/packages/utils.py @@ -96,6 +96,8 @@ SELECT p.id, q.id p.pkgver != q.pkgver OR p.pkgrel != q.pkgrel + OR + p.epoch != q.epoch ) """ cursor = connection.cursor() -- cgit v1.2.3-2-g168b From ba1ca7db1e16400651bb746b8b80f2b30cf88a2f Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 13 Mar 2011 12:02:59 -0500 Subject: Ensure PyPy compatibility Unfortunately I was relying on all python environments having this method defined, which is not true yet. Signed-off-by: Dan McGee --- packages/templatetags/package_extras.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'packages') diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py index 24264af0..dd5b9347 100644 --- a/packages/templatetags/package_extras.py +++ b/packages/templatetags/package_extras.py @@ -1,5 +1,8 @@ import urllib -import urlparse +try: + from urlparse import parse_qs +except ImportError: + from cgi import parse_qs from django import template from django.utils.html import escape @@ -11,7 +14,7 @@ class BuildQueryStringNode(template.Node): self.sortfield = sortfield def render(self, context): - qs = urlparse.parse_qs(context['current_query']) + qs = parse_qs(context['current_query']) if qs.has_key('sort') and self.sortfield in qs['sort']: if self.sortfield.startswith('-'): qs['sort'] = [self.sortfield[1:]] -- cgit v1.2.3-2-g168b From a0ef88770f5fe318f38eaa7dc794727a507c797b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 15 Mar 2011 09:02:22 -0500 Subject: Ensure package search form correctly handles errors We were silently eating errors and just showing a normal package list if the form didn't validate. Rather than do that, make sure we return no packages at all and display the form errors back to the user in a sane fashion. Adjust the validation methods on the 'limit' parameter so any integer is acceptable. Signed-off-by: Dan McGee --- packages/views.py | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'packages') diff --git a/packages/views.py b/packages/views.py index 3cef8226..6239f01a 100644 --- a/packages/views.py +++ b/packages/views.py @@ -126,6 +126,23 @@ def getmaintainer(request, name, repo, arch): return HttpResponse(str('\n'.join(names)), mimetype='text/plain') +def coerce_limit_value(value): + if not value: + return 50 + if value == 'all': + return None + value = int(value) + if value < 0: + raise ValueError + return value + +class LimitTypedChoiceField(forms.TypedChoiceField): + def valid_value(self, value): + try: + return coerce_limit_value(value) + except ValueError, TypeError: + return False + class PackageSearchForm(forms.Form): repo = forms.MultipleChoiceField(required=False) arch = forms.MultipleChoiceField(required=False) @@ -136,25 +153,12 @@ class PackageSearchForm(forms.Form): flagged = forms.ChoiceField( choices=[('', 'All')] + make_choice(['Flagged', 'Not Flagged']), required=False) - limit = forms.ChoiceField( + limit = LimitTypedChoiceField( choices=make_choice([50, 100, 250]) + [('all', 'All')], + coerce=coerce_limit_value, required=False, initial=50) - def clean_limit(self): - limit = self.cleaned_data['limit'] - if limit == 'all': - limit = None - elif limit: - try: - limit = int(limit) - except: - raise forms.ValidationError("Should be an integer") - else: - limit = 50 - return limit - - def __init__(self, *args, **kwargs): super(PackageSearchForm, self).__init__(*args, **kwargs) self.fields['repo'].choices = make_choice( @@ -186,7 +190,8 @@ def search(request, page=None): inner_q = PackageRelation.objects.all().values('pkgbase') packages = packages.exclude(pkgbase__in=inner_q) elif form.cleaned_data['maintainer']: - inner_q = PackageRelation.objects.filter(user__username=form.cleaned_data['maintainer']).values('pkgbase') + inner_q = PackageRelation.objects.filter( + user__username=form.cleaned_data['maintainer']).values('pkgbase') packages = packages.filter(pkgbase__in=inner_q) if form.cleaned_data['flagged'] == 'Flagged': @@ -203,6 +208,9 @@ def search(request, page=None): packages = packages.filter(last_update__gte= datetime(lu.year, lu.month, lu.day, 0, 0)) limit = form.cleaned_data['limit'] + else: + # Form had errors, don't return any results, just the busted form + packages = Package.objects.none() else: form = PackageSearchForm() -- cgit v1.2.3-2-g168b From 2360e2c4bcb0fc873a60599165e7f24f20465786 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 15 Mar 2011 11:06:34 -0500 Subject: Only set limit if we have one, else default to 50 This was the cause of some pretty awesome performance headaches this morning. Signed-off-by: Dan McGee --- packages/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/views.py b/packages/views.py index 6239f01a..70b3a84b 100644 --- a/packages/views.py +++ b/packages/views.py @@ -207,7 +207,9 @@ def search(request, page=None): lu = form.cleaned_data['last_update'] packages = packages.filter(last_update__gte= datetime(lu.year, lu.month, lu.day, 0, 0)) - limit = form.cleaned_data['limit'] + + if form.cleaned_data['limit']: + limit = form.cleaned_data['limit'] else: # Form had errors, don't return any results, just the busted form packages = Package.objects.none() -- cgit v1.2.3-2-g168b From aca7700dd7519d45e677e18b1a0199f3712ce140 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Wed, 16 Mar 2011 09:03:38 +0100 Subject: Fix valid_value() in "LimitTypedChoiceField" class. We just returned the coerced value in valid_value() which may become None if the valid value "all" was passed, resulting in valid_value() evaluating to False. Explicitly returning True if the value can be coerced without an error fixes this. Signed-off-by: Lukas Fleischer Signed-off-by: Dan McGee --- packages/views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'packages') diff --git a/packages/views.py b/packages/views.py index 70b3a84b..4101c538 100644 --- a/packages/views.py +++ b/packages/views.py @@ -128,9 +128,10 @@ def getmaintainer(request, name, repo, arch): def coerce_limit_value(value): if not value: - return 50 - if value == 'all': return None + if value == 'all': + # negative value indicates show all results + return -1 value = int(value) if value < 0: raise ValueError @@ -139,7 +140,8 @@ def coerce_limit_value(value): class LimitTypedChoiceField(forms.TypedChoiceField): def valid_value(self, value): try: - return coerce_limit_value(value) + coerce_limit_value(value) + return True except ValueError, TypeError: return False @@ -208,8 +210,11 @@ def search(request, page=None): packages = packages.filter(last_update__gte= datetime(lu.year, lu.month, lu.day, 0, 0)) - if form.cleaned_data['limit']: - limit = form.cleaned_data['limit'] + asked_limit = form.cleaned_data['limit'] + if asked_limit and asked_limit < 0: + limit = None + elif asked_limit: + limit = asked_limit else: # Form had errors, don't return any results, just the busted form packages = Package.objects.none() -- cgit v1.2.3-2-g168b