From b59e79f3878d59b83c6867eb5c6196f8f003dcd9 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 1 May 2012 17:13:33 -0500
Subject: Opensearch enhancements
* Add a 64x64 icon as indicated in the Opensearch specification.
* Add suggestions capability and a new view providing suggestions based
on package name starting with the typed value.
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 6a9c5275..21d17470 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -7,7 +7,7 @@
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404, redirect
from django.utils import simplejson
-from django.views.decorators.http import require_POST
+from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.vary import vary_on_headers
from django.views.generic.simple import direct_to_template
@@ -24,6 +24,7 @@
from .signoff import signoffs, signoff_package, signoff_options, signoffs_json
+@require_GET
def opensearch(request):
if request.is_secure():
domain = "https://%s" % request.META['HTTP_HOST']
@@ -34,6 +35,21 @@ def opensearch(request):
{'domain': domain},
mimetype='application/opensearchdescription+xml')
+
+@require_GET
+def opensearch_suggest(request):
+ search_term = request.GET.get('q', '')
+ if search_term == '':
+ return HttpResponse('', mimetype='application/x-suggestions+json')
+
+ names = Package.objects.filter(
+ pkgname__startswith=search_term).values_list(
+ 'pkgname', flat=True).order_by('pkgname').distinct()[:10]
+ results = [search_term, list(names)]
+ to_json = simplejson.dumps(results, ensure_ascii=False)
+ return HttpResponse(to_json, mimetype='application/x-suggestions+json')
+
+
@permission_required('main.change_package')
@require_POST
def update(request):
--
cgit v1.2.3-54-g00ecf
From f3e0adcb2fc9a26e2ad9337a47550a37590074d9 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 1 May 2012 18:12:50 -0500
Subject: Add some caching to the Opensearch-related views
Both some simple cache headers as well as low-level results caching on
search terms suggestions.
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 21d17470..0f1dc799 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -4,9 +4,11 @@
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import User
+from django.core.cache import cache
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404, redirect
from django.utils import simplejson
+from django.views.decorators.cache import cache_control
from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.vary import vary_on_headers
from django.views.generic.simple import direct_to_template
@@ -25,6 +27,7 @@
@require_GET
+@cache_control(public=True, max_age=86400)
def opensearch(request):
if request.is_secure():
domain = "https://%s" % request.META['HTTP_HOST']
@@ -37,16 +40,21 @@ def opensearch(request):
@require_GET
+@cache_control(public=True, max_age=300)
def opensearch_suggest(request):
search_term = request.GET.get('q', '')
if search_term == '':
return HttpResponse('', mimetype='application/x-suggestions+json')
- names = Package.objects.filter(
- pkgname__startswith=search_term).values_list(
- 'pkgname', flat=True).order_by('pkgname').distinct()[:10]
- results = [search_term, list(names)]
- to_json = simplejson.dumps(results, ensure_ascii=False)
+ cache_key = 'opensearch:packages:' + search_term
+ to_json = cache.get(cache_key, None)
+ if to_json is None:
+ names = Package.objects.filter(
+ pkgname__startswith=search_term).values_list(
+ 'pkgname', flat=True).order_by('pkgname').distinct()[:10]
+ results = [search_term, list(names)]
+ to_json = simplejson.dumps(results, ensure_ascii=False)
+ cache.set('opensearch:packages:%s' % search_term, to_json, 300)
return HttpResponse(to_json, mimetype='application/x-suggestions+json')
--
cgit v1.2.3-54-g00ecf
From 768bc688aab844cf9fdf9809b9381aaf0042f2fc Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Wed, 2 May 2012 10:21:30 -0500
Subject: Flagging related cleanups and improvements
Touch up the style slightly on the flag help popup to match the main
site style more closely.
When a logged-in user is flagging a package out of date, we have no need
for them to fill in the email field since we already have an email
address on file.
Signed-off-by: Dan McGee
---
packages/views/flag.py | 34 ++++++++++++++++++++++++----------
templates/packages/flaghelp.html | 20 +++++++++-----------
2 files changed, 33 insertions(+), 21 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/flag.py b/packages/views/flag.py
index 0d2f9009..7fa2d508 100644
--- a/packages/views/flag.py
+++ b/packages/views/flag.py
@@ -6,16 +6,13 @@
from django.shortcuts import get_object_or_404, redirect
from django.template import loader, Context
from django.views.generic.simple import direct_to_template
-from django.views.decorators.cache import never_cache
+from django.views.decorators.cache import cache_page, never_cache
from ..models import FlagRequest
from main.models import Package
from main.utils import utc_now
-def flaghelp(request):
- return direct_to_template(request, 'packages/flaghelp.html')
-
class FlagForm(forms.Form):
email = forms.EmailField(label='E-mail Address')
message = forms.CharField(label='Message To Developer',
@@ -26,6 +23,20 @@ class FlagForm(forms.Form):
widget=forms.TextInput(attrs={'style': 'display:none;'}),
required=False)
+ def __init__(self, *args, **kwargs):
+ # we remove the 'email' field if this form is being shown to a
+ # logged-in user, e.g., a developer.
+ auth = kwargs.pop('authenticated', False)
+ super(FlagForm, self).__init__(*args, **kwargs)
+ if auth:
+ del self.fields['email']
+
+
+@cache_page(3600)
+def flaghelp(request):
+ return direct_to_template(request, 'packages/flaghelp.html')
+
+
@never_cache
def flag(request, name, repo, arch):
pkg = get_object_or_404(Package,
@@ -41,8 +52,10 @@ def flag(request, name, repo, arch):
repo__staging=pkg.repo.staging).order_by(
'pkgname', 'repo__name', 'arch__name')
+ authenticated = request.user.is_authenticated()
+
if request.POST:
- form = FlagForm(request.POST)
+ form = FlagForm(request.POST, authenticated=authenticated)
if form.is_valid() and form.cleaned_data['website'] == '':
# save the package list for later use
flagged_pkgs = list(pkgs)
@@ -54,9 +67,12 @@ def flag(request, name, repo, arch):
else:
version = ''
- email = form.cleaned_data['email']
message = form.cleaned_data['message']
ip_addr = request.META.get('REMOTE_ADDR')
+ if authenticated:
+ email = request.user.email
+ else:
+ email = form.cleaned_data['email']
@transaction.commit_on_success
def perform_updates():
@@ -68,7 +84,7 @@ def perform_updates():
ip_address=ip_addr, pkgbase=pkg.pkgbase,
version=version, repo=pkg.repo,
num_packages=len(flagged_pkgs))
- if request.user.is_authenticated():
+ if authenticated:
flag_request.user = request.user
flag_request.save()
@@ -106,9 +122,7 @@ def perform_updates():
arch=arch)
else:
initial = {}
- if request.user.is_authenticated():
- initial['email'] = request.user.email
- form = FlagForm(initial=initial)
+ form = FlagForm(authenticated=authenticated)
context = {
'package': pkg,
diff --git a/templates/packages/flaghelp.html b/templates/packages/flaghelp.html
index 819a2f01..399b7e01 100644
--- a/templates/packages/flaghelp.html
+++ b/templates/packages/flaghelp.html
@@ -1,20 +1,19 @@
-
+{% load static from staticfiles %}
Flagging Packages
-
-
Flagging Packages
-
If you notice that a package is out-of-date (i.e., there is a newer
stable release available), then please notify us by
using the Flag button in the Package Details
@@ -29,8 +28,7 @@
Flagging Packages
with your additional text.
Note: Please do not use this facility if the
- package is broken! Use the bugtracker instead.
-
--
cgit v1.2.3-54-g00ecf
From 86f8efaeb1f67138c194d0c373f9d91e2999c5dd Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Fri, 4 May 2012 10:57:59 -0500
Subject: Fix search suggestions for invalid cache keys
Unfortunately, "invalid" in this case includes spaces, which is a bit
crazy. MD5 the provided search term before using it as a cache key to be
safe.
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 0f1dc799..559368b9 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -1,3 +1,4 @@
+import hashlib
from string import Template
from urllib import urlencode
@@ -46,7 +47,7 @@ def opensearch_suggest(request):
if search_term == '':
return HttpResponse('', mimetype='application/x-suggestions+json')
- cache_key = 'opensearch:packages:' + search_term
+ cache_key = 'opensearch:packages:' + hashlib.md5(search_term).hexdigest()
to_json = cache.get(cache_key, None)
if to_json is None:
names = Package.objects.filter(
@@ -54,7 +55,7 @@ def opensearch_suggest(request):
'pkgname', flat=True).order_by('pkgname').distinct()[:10]
results = [search_term, list(names)]
to_json = simplejson.dumps(results, ensure_ascii=False)
- cache.set('opensearch:packages:%s' % search_term, to_json, 300)
+ cache.set(cache_key, to_json, 300)
return HttpResponse(to_json, mimetype='application/x-suggestions+json')
--
cgit v1.2.3-54-g00ecf
From d4c7a48623f90cdc508d1824bf47ce3e398dd820 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Sat, 5 May 2012 10:19:49 -0500
Subject: Fix suggestion caching again for non-ASCII characters
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is why you should test this stuff with random input before rolling
it out. Whoops. URL that caught this problem:
/opensearch/packages/suggest?q=%D7%A0%D7%9F%D7%92%D7%9F
aka
/opensearch/packages/suggest?q=נןגן
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 559368b9..60c3a46b 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -47,7 +47,8 @@ def opensearch_suggest(request):
if search_term == '':
return HttpResponse('', mimetype='application/x-suggestions+json')
- cache_key = 'opensearch:packages:' + hashlib.md5(search_term).hexdigest()
+ cache_key = 'opensearch:packages:' + \
+ hashlib.md5(search_term.encode('utf-8')).hexdigest()
to_json = cache.get(cache_key, None)
if to_json is None:
names = Package.objects.filter(
--
cgit v1.2.3-54-g00ecf
From a5f5557493446bede78adb0584c88208234f874e Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Sat, 12 May 2012 09:32:30 -0500
Subject: Use python json module directly in place of simplejson
As of Python 2.6, this is a builtin module that has all the same
functions and capabilities of the Django simplejson module. Additionally
simplejson is deprecated in the upcoming Django 1.5 release.
Signed-off-by: Dan McGee
---
mirrors/views.py | 5 ++---
packages/views/__init__.py | 10 ++++------
packages/views/search.py | 5 ++---
packages/views/signoff.py | 7 +++----
todolists/views.py | 6 +++---
visualize/views.py | 8 ++++----
6 files changed, 18 insertions(+), 23 deletions(-)
(limited to 'packages/views')
diff --git a/mirrors/views.py b/mirrors/views.py
index eac78ff2..b0be6238 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -1,5 +1,6 @@
from datetime import timedelta
from itertools import groupby
+import json
from operator import attrgetter, itemgetter
from django import forms
@@ -10,7 +11,6 @@
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.simple import direct_to_template
-from django.utils import simplejson
from django_countries.countries import COUNTRIES
from .models import Mirror, MirrorUrl, MirrorProtocol
@@ -237,8 +237,7 @@ def status_json(request):
status_info = get_mirror_statuses()
data = status_info.copy()
data['version'] = 3
- to_json = simplejson.dumps(data, ensure_ascii=False,
- cls=MirrorStatusJSONEncoder)
+ to_json = json.dumps(data, ensure_ascii=False, cls=MirrorStatusJSONEncoder)
response = HttpResponse(to_json, mimetype='application/json')
return response
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 60c3a46b..c1a035d0 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -1,4 +1,5 @@
import hashlib
+import json
from string import Template
from urllib import urlencode
@@ -8,7 +9,6 @@
from django.core.cache import cache
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404, redirect
-from django.utils import simplejson
from django.views.decorators.cache import cache_control
from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.vary import vary_on_headers
@@ -55,7 +55,7 @@ def opensearch_suggest(request):
pkgname__startswith=search_term).values_list(
'pkgname', flat=True).order_by('pkgname').distinct()[:10]
results = [search_term, list(names)]
- to_json = simplejson.dumps(results, ensure_ascii=False)
+ to_json = json.dumps(results, ensure_ascii=False)
cache.set(cache_key, to_json, 300)
return HttpResponse(to_json, mimetype='application/x-suggestions+json')
@@ -197,8 +197,7 @@ def files(request, name, repo, arch):
def details_json(request, name, repo, arch):
pkg = get_object_or_404(Package,
pkgname=name, repo__name__iexact=repo, arch__name=arch)
- to_json = simplejson.dumps(pkg, ensure_ascii=False,
- cls=PackageJSONEncoder)
+ to_json = json.dumps(pkg, ensure_ascii=False, cls=PackageJSONEncoder)
return HttpResponse(to_json, mimetype='application/json')
def files_json(request, name, repo, arch):
@@ -212,8 +211,7 @@ def files_json(request, name, repo, arch):
'arch': pkg.arch.name.lower(),
'files': fileslist,
}
- to_json = simplejson.dumps(data, ensure_ascii=False,
- cls=PackageJSONEncoder)
+ to_json = json.dumps(data, ensure_ascii=False, cls=PackageJSONEncoder)
return HttpResponse(to_json, mimetype='application/json')
def download(request, name, repo, arch):
diff --git a/packages/views/search.py b/packages/views/search.py
index a09de0a7..a89822be 100644
--- a/packages/views/search.py
+++ b/packages/views/search.py
@@ -1,4 +1,5 @@
from datetime import datetime
+import json
from django import forms
from django.contrib.admin.widgets import AdminDateWidget
@@ -6,7 +7,6 @@
from django.db.models import Q
from django.http import HttpResponse
from django.views.generic import list_detail
-from django.utils import simplejson
from main.models import Package, Arch, Repo
from main.utils import make_choice
@@ -179,8 +179,7 @@ def search_json(request):
container['results'] = packages
container['valid'] = True
- to_json = simplejson.dumps(container, ensure_ascii=False,
- cls=PackageJSONEncoder)
+ to_json = json.dumps(container, ensure_ascii=False, cls=PackageJSONEncoder)
return HttpResponse(to_json, mimetype='application/json')
# vim: set ts=4 sw=4 et:
diff --git a/packages/views/signoff.py b/packages/views/signoff.py
index 63341a1d..61d949fc 100644
--- a/packages/views/signoff.py
+++ b/packages/views/signoff.py
@@ -1,3 +1,4 @@
+import json
from operator import attrgetter
from django import forms
@@ -7,7 +8,6 @@
from django.db import transaction
from django.http import HttpResponse, Http404
from django.shortcuts import get_list_or_404, redirect, render
-from django.utils import simplejson
from django.views.decorators.cache import never_cache
from django.views.generic.simple import direct_to_template
@@ -67,7 +67,7 @@ def signoff_package(request, name, repo, arch, revoke=False):
'known_bad': spec.known_bad,
'user': str(request.user),
}
- return HttpResponse(simplejson.dumps(data, ensure_ascii=False),
+ return HttpResponse(json.dumps(data, ensure_ascii=False),
mimetype='application/json')
return redirect('package-signoffs')
@@ -183,8 +183,7 @@ def signoffs_json(request):
'version': 2,
'signoff_groups': signoff_groups,
}
- to_json = simplejson.dumps(data, ensure_ascii=False,
- cls=SignoffJSONEncoder)
+ to_json = json.dumps(data, ensure_ascii=False, cls=SignoffJSONEncoder)
response = HttpResponse(to_json, mimetype='application/json')
return response
diff --git a/todolists/views.py b/todolists/views.py
index 70209b6d..b9ba0903 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -1,5 +1,6 @@
-from django import forms
+import json
+from django import forms
from django.http import HttpResponse
from django.core.mail import send_mail
from django.shortcuts import get_list_or_404, get_object_or_404, redirect
@@ -9,7 +10,6 @@
from django.views.generic import DeleteView
from django.views.generic.simple import direct_to_template
from django.template import Context, loader
-from django.utils import simplejson
from main.models import Todolist, TodolistPkg, Package, Repo
from packages.utils import attach_maintainers
@@ -42,7 +42,7 @@ def flag(request, list_id, pkg_id):
pkg.save()
if request.is_ajax():
return HttpResponse(
- simplejson.dumps({'complete': pkg.complete}),
+ json.dumps({'complete': pkg.complete}),
mimetype='application/json')
return redirect(todolist)
diff --git a/visualize/views.py b/visualize/views.py
index afc5429d..95f8c314 100644
--- a/visualize/views.py
+++ b/visualize/views.py
@@ -1,9 +1,9 @@
from datetime import datetime
+import json
from django.contrib.auth.models import User
from django.db.models import Count, Sum, Q
from django.http import HttpResponse
-from django.utils import simplejson
from django.views.decorators.cache import cache_page
from django.views.generic.simple import direct_to_template
@@ -61,13 +61,13 @@ def build_map(name, arch, repo):
@cache_page(1800)
def by_arch(request):
data = arch_repo_data()
- to_json = simplejson.dumps(data['by_arch'], ensure_ascii=False)
+ to_json = json.dumps(data['by_arch'], ensure_ascii=False)
return HttpResponse(to_json, mimetype='application/json')
@cache_page(1800)
def by_repo(request):
data = arch_repo_data()
- to_json = simplejson.dumps(data['by_repo'], ensure_ascii=False)
+ to_json = json.dumps(data['by_repo'], ensure_ascii=False)
return HttpResponse(to_json, mimetype='application/json')
@@ -109,7 +109,7 @@ def pgp_keys(request):
data = { 'nodes': node_list, 'edges': edge_list }
- to_json = simplejson.dumps(data, ensure_ascii=False)
+ to_json = json.dumps(data, ensure_ascii=False)
return HttpResponse(to_json, mimetype='application/json')
# vim: set ts=4 sw=4 et:
--
cgit v1.2.3-54-g00ecf
From cf67e7952396121d3f7190195d812ea3f5fc7dcf Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Fri, 18 May 2012 20:26:16 -0500
Subject: Issue redirects from non-agnostic to agnostic URLs if unambiguous
For something like "/extra/i686/apache-ant/", we can redirect to
"/extra/any/apache-ant/" without ambiguity. Previously this redirected
to the split packages listing with a single package, which was neither
correct nor really expected.
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 10 ++++++++++
1 file changed, 10 insertions(+)
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index c1a035d0..3e574c26 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -136,6 +136,16 @@ def details(request, name='', repo='', arch=''):
return direct_to_template(request, 'packages/details.html',
{'pkg': pkg, })
except Package.DoesNotExist:
+ arch_obj = get_object_or_404(Arch, name=arch)
+ # for arch='any' packages, we can issue a redirect to them if we
+ # have a single non-ambiguous option by changing the arch to match
+ # any arch-agnostic package
+ if not arch_obj.agnostic:
+ pkgs = Package.objects.select_related(
+ 'arch', 'repo', 'packager').filter(pkgname=name,
+ repo__name__iexact=repo, arch__agnostic=True)
+ if len(pkgs) == 1:
+ return redirect(pkgs[0], permanent=True)
return split_package_details(request, name, repo, arch)
else:
pkg_data = [
--
cgit v1.2.3-54-g00ecf
From 872d4bcaa2ce85d2d319a1146e0fc05ab6808eb9 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Sat, 21 Jul 2012 11:26:34 -0500
Subject: Split details/display package views into new module
This moves a lot of the package and group display logic into a new view
module, similar to what we already did earlier with a bunch of other
views.
Signed-off-by: Dan McGee
---
packages/views/__init__.py | 154 ++-----------------------------------------
packages/views/display.py | 160 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 167 insertions(+), 147 deletions(-)
create mode 100644 packages/views/display.py
(limited to 'packages/views')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 3e574c26..fa67daa8 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -1,27 +1,24 @@
import hashlib
import json
-from string import Template
-from urllib import urlencode
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import User
from django.core.cache import cache
-from django.http import HttpResponse, Http404
-from django.shortcuts import get_object_or_404, redirect
+from django.http import HttpResponse
+from django.shortcuts import redirect
from django.views.decorators.cache import cache_control
from django.views.decorators.http import require_GET, require_POST
-from django.views.decorators.vary import vary_on_headers
from django.views.generic.simple import direct_to_template
-from main.models import Package, PackageFile, Arch, Repo
-from mirrors.models import MirrorUrl
-from mirrors.utils import get_mirror_url_for_download
+from main.models import Package, Arch
from ..models import PackageRelation
-from ..utils import (get_group_info, get_differences_info,
- multilib_differences, get_wrong_permissions, PackageJSONEncoder)
+from ..utils import (get_differences_info,
+ multilib_differences, get_wrong_permissions)
# make other views available from this same package
+from .display import (details, groups, group_details, files, details_json,
+ files_json, download)
from .flag import flaghelp, flag, flag_confirmed, unflag, unflag_all
from .search import search, search_json
from .signoff import signoffs, signoff_package, signoff_options, signoffs_json
@@ -105,143 +102,6 @@ def update(request):
messages.error(request, "Are you trying to adopt or disown?")
return redirect('/packages/')
-def split_package_details(request, name='', repo='', arch=''):
- arch = get_object_or_404(Arch, name=arch)
- arches = [ arch ]
- arches.extend(Arch.objects.filter(agnostic=True))
- repo = get_object_or_404(Repo, name__iexact=repo)
- pkgs = Package.objects.normal().filter(pkgbase=name,
- repo__testing=repo.testing, repo__staging=repo.staging,
- arch__in=arches).order_by('pkgname')
- if len(pkgs) == 0:
- raise Http404
- # we have packages, but ensure at least one is in the given repo
- if not any(True for pkg in pkgs if pkg.repo == repo):
- raise Http404
- context = {
- 'list_title': 'Split Package Details',
- 'name': name,
- 'arch': arch,
- 'packages': pkgs,
- }
- return direct_to_template(request, 'packages/packages_list.html',
- context)
-
-def details(request, name='', repo='', arch=''):
- if all([name, repo, arch]):
- try:
- pkg = Package.objects.select_related(
- 'arch', 'repo', 'packager').get(pkgname=name,
- repo__name__iexact=repo, arch__name=arch)
- return direct_to_template(request, 'packages/details.html',
- {'pkg': pkg, })
- except Package.DoesNotExist:
- arch_obj = get_object_or_404(Arch, name=arch)
- # for arch='any' packages, we can issue a redirect to them if we
- # have a single non-ambiguous option by changing the arch to match
- # any arch-agnostic package
- if not arch_obj.agnostic:
- pkgs = Package.objects.select_related(
- 'arch', 'repo', 'packager').filter(pkgname=name,
- repo__name__iexact=repo, arch__agnostic=True)
- if len(pkgs) == 1:
- return redirect(pkgs[0], permanent=True)
- return split_package_details(request, name, repo, arch)
- else:
- pkg_data = [
- ('arch', arch.lower()),
- ('repo', repo.lower()),
- ('q', name),
- ]
- # only include non-blank values in the query we generate
- pkg_data = [(x, y.encode('utf-8')) for x, y in pkg_data if y]
- return redirect("/packages/?%s" % urlencode(pkg_data))
-
-def groups(request, arch=None):
- arches = []
- if arch:
- get_object_or_404(Arch, name=arch, agnostic=False)
- arches.append(arch)
- grps = get_group_info(arches)
- context = {
- 'groups': grps,
- 'arch': arch,
- }
- return direct_to_template(request, 'packages/groups.html', context)
-
-def group_details(request, arch, name):
- arch = get_object_or_404(Arch, name=arch)
- arches = [ arch ]
- arches.extend(Arch.objects.filter(agnostic=True))
- pkgs = Package.objects.normal().filter(
- groups__name=name, arch__in=arches).order_by('pkgname')
- if len(pkgs) == 0:
- raise Http404
- context = {
- 'list_title': 'Group Details',
- 'name': name,
- 'arch': arch,
- 'packages': pkgs,
- }
- return direct_to_template(request, 'packages/packages_list.html', context)
-
-@vary_on_headers('X-Requested-With')
-def files(request, name, repo, arch):
- pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
- # files are inserted in sorted order, so preserve that
- fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
- dir_count = sum(1 for f in fileslist if f.is_directory)
- files_count = len(fileslist) - dir_count
- context = {
- 'pkg': pkg,
- 'files': fileslist,
- 'files_count': files_count,
- 'dir_count': dir_count,
- }
- template = 'packages/files.html'
- if request.is_ajax():
- template = 'packages/files_list.html'
- return direct_to_template(request, template, context)
-
-def details_json(request, name, repo, arch):
- pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
- to_json = json.dumps(pkg, ensure_ascii=False, cls=PackageJSONEncoder)
- return HttpResponse(to_json, mimetype='application/json')
-
-def files_json(request, name, repo, arch):
- pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
- # files are inserted in sorted order, so preserve that
- fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
- data = {
- 'pkgname': pkg.pkgname,
- 'repo': pkg.repo.name.lower(),
- 'arch': pkg.arch.name.lower(),
- 'files': fileslist,
- }
- to_json = json.dumps(data, ensure_ascii=False, cls=PackageJSONEncoder)
- return HttpResponse(to_json, mimetype='application/json')
-
-def download(request, name, repo, arch):
- pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
- url = get_mirror_url_for_download()
- if not url:
- raise Http404
- arch = pkg.arch.name
- if pkg.arch.agnostic:
- # grab the first non-any arch to fake the download path
- arch = Arch.objects.exclude(agnostic=True)[0].name
- values = {
- 'host': url.url,
- 'arch': arch,
- 'repo': pkg.repo.name.lower(),
- 'file': pkg.filename,
- }
- url = Template('${host}${repo}/os/${arch}/${file}').substitute(values)
- return redirect(url)
def arch_differences(request):
# TODO: we have some hardcoded magic here with respect to the arches.
diff --git a/packages/views/display.py b/packages/views/display.py
new file mode 100644
index 00000000..dd57571a
--- /dev/null
+++ b/packages/views/display.py
@@ -0,0 +1,160 @@
+import json
+from string import Template
+from urllib import urlencode
+
+from django.http import HttpResponse, Http404
+from django.shortcuts import get_object_or_404, redirect
+from django.views.generic.simple import direct_to_template
+from django.views.decorators.vary import vary_on_headers
+
+from main.models import Package, PackageFile, Arch, Repo
+from mirrors.utils import get_mirror_url_for_download
+from ..utils import get_group_info, PackageJSONEncoder
+
+
+def split_package_details(request, name='', repo='', arch=''):
+ arch = get_object_or_404(Arch, name=arch)
+ arches = [ arch ]
+ arches.extend(Arch.objects.filter(agnostic=True))
+ repo = get_object_or_404(Repo, name__iexact=repo)
+ pkgs = Package.objects.normal().filter(pkgbase=name,
+ repo__testing=repo.testing, repo__staging=repo.staging,
+ arch__in=arches).order_by('pkgname')
+ if len(pkgs) == 0:
+ raise Http404
+ # we have packages, but ensure at least one is in the given repo
+ if not any(True for pkg in pkgs if pkg.repo == repo):
+ raise Http404
+ context = {
+ 'list_title': 'Split Package Details',
+ 'name': name,
+ 'arch': arch,
+ 'packages': pkgs,
+ }
+ return direct_to_template(request, 'packages/packages_list.html',
+ context)
+
+
+def details(request, name='', repo='', arch=''):
+ if all([name, repo, arch]):
+ try:
+ pkg = Package.objects.select_related(
+ 'arch', 'repo', 'packager').get(pkgname=name,
+ repo__name__iexact=repo, arch__name=arch)
+ return direct_to_template(request, 'packages/details.html',
+ {'pkg': pkg, })
+ except Package.DoesNotExist:
+ arch_obj = get_object_or_404(Arch, name=arch)
+ # for arch='any' packages, we can issue a redirect to them if we
+ # have a single non-ambiguous option by changing the arch to match
+ # any arch-agnostic package
+ if not arch_obj.agnostic:
+ pkgs = Package.objects.select_related(
+ 'arch', 'repo', 'packager').filter(pkgname=name,
+ repo__name__iexact=repo, arch__agnostic=True)
+ if len(pkgs) == 1:
+ return redirect(pkgs[0], permanent=True)
+ return split_package_details(request, name, repo, arch)
+ else:
+ pkg_data = [
+ ('arch', arch.lower()),
+ ('repo', repo.lower()),
+ ('q', name),
+ ]
+ # only include non-blank values in the query we generate
+ pkg_data = [(x, y.encode('utf-8')) for x, y in pkg_data if y]
+ return redirect("/packages/?%s" % urlencode(pkg_data))
+
+
+def groups(request, arch=None):
+ arches = []
+ if arch:
+ get_object_or_404(Arch, name=arch, agnostic=False)
+ arches.append(arch)
+ grps = get_group_info(arches)
+ context = {
+ 'groups': grps,
+ 'arch': arch,
+ }
+ return direct_to_template(request, 'packages/groups.html', context)
+
+
+def group_details(request, arch, name):
+ arch = get_object_or_404(Arch, name=arch)
+ arches = [ arch ]
+ arches.extend(Arch.objects.filter(agnostic=True))
+ pkgs = Package.objects.normal().filter(
+ groups__name=name, arch__in=arches).order_by('pkgname')
+ if len(pkgs) == 0:
+ raise Http404
+ context = {
+ 'list_title': 'Group Details',
+ 'name': name,
+ 'arch': arch,
+ 'packages': pkgs,
+ }
+ return direct_to_template(request, 'packages/packages_list.html', context)
+
+
+@vary_on_headers('X-Requested-With')
+def files(request, name, repo, arch):
+ pkg = get_object_or_404(Package,
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ # files are inserted in sorted order, so preserve that
+ fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
+ dir_count = sum(1 for f in fileslist if f.is_directory)
+ files_count = len(fileslist) - dir_count
+ context = {
+ 'pkg': pkg,
+ 'files': fileslist,
+ 'files_count': files_count,
+ 'dir_count': dir_count,
+ }
+ template = 'packages/files.html'
+ if request.is_ajax():
+ template = 'packages/files_list.html'
+ return direct_to_template(request, template, context)
+
+
+def details_json(request, name, repo, arch):
+ pkg = get_object_or_404(Package,
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ to_json = json.dumps(pkg, ensure_ascii=False, cls=PackageJSONEncoder)
+ return HttpResponse(to_json, mimetype='application/json')
+
+
+def files_json(request, name, repo, arch):
+ pkg = get_object_or_404(Package,
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ # files are inserted in sorted order, so preserve that
+ fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
+ data = {
+ 'pkgname': pkg.pkgname,
+ 'repo': pkg.repo.name.lower(),
+ 'arch': pkg.arch.name.lower(),
+ 'files': fileslist,
+ }
+ to_json = json.dumps(data, ensure_ascii=False, cls=PackageJSONEncoder)
+ return HttpResponse(to_json, mimetype='application/json')
+
+
+def download(request, name, repo, arch):
+ pkg = get_object_or_404(Package,
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ url = get_mirror_url_for_download()
+ if not url:
+ raise Http404
+ arch = pkg.arch.name
+ if pkg.arch.agnostic:
+ # grab the first non-any arch to fake the download path
+ arch = Arch.objects.exclude(agnostic=True)[0].name
+ values = {
+ 'host': url.url,
+ 'arch': arch,
+ 'repo': pkg.repo.name.lower(),
+ 'file': pkg.filename,
+ }
+ url = Template('${host}${repo}/os/${arch}/${file}').substitute(values)
+ return redirect(url)
+
+# vim: set ts=4 sw=4 et:
--
cgit v1.2.3-54-g00ecf
From 946d90d08f29094153142056a1778cd595e568a3 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Mon, 23 Jul 2012 09:45:44 -0500
Subject: Add '410 Gone' support for packages moved out of repositories
This allows us to do better than a generic 404 handler when we know a
package previously existed in a given repository, and should also make
things a bit nicer when getting sent in from a search engine to a page
that no longer exists.
Signed-off-by: Dan McGee
---
packages/models.py | 3 +++
packages/views/display.py | 46 ++++++++++++++++++++++++++++++++++++-----
templates/packages/removed.html | 28 +++++++++++++++++++++++++
3 files changed, 72 insertions(+), 5 deletions(-)
create mode 100644 templates/packages/removed.html
(limited to 'packages/views')
diff --git a/packages/models.py b/packages/models.py
index 45ff3c08..18a62a3c 100644
--- a/packages/models.py
+++ b/packages/models.py
@@ -297,6 +297,9 @@ def new_version(self):
return u'%d:%s-%s' % (self.new_epoch, self.new_pkgver, self.new_pkgrel)
return u'%s-%s' % (self.new_pkgver, self.new_pkgrel)
+ def elsewhere(self):
+ return Package.objects.filter(pkgname=self.pkgname, arch=self.arch)
+
def __unicode__(self):
return u'%s of %s on %s' % (self.get_action_flag_display(),
self.pkgname, self.created)
diff --git a/packages/views/display.py b/packages/views/display.py
index dd57571a..5332dc13 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -1,18 +1,21 @@
+import datetime
import json
from string import Template
from urllib import urlencode
from django.http import HttpResponse, Http404
-from django.shortcuts import get_object_or_404, redirect
+from django.shortcuts import get_object_or_404, redirect, render
+from django.utils.timezone import now
from django.views.generic.simple import direct_to_template
from django.views.decorators.vary import vary_on_headers
from main.models import Package, PackageFile, Arch, Repo
from mirrors.utils import get_mirror_url_for_download
+from ..models import Update
from ..utils import get_group_info, PackageJSONEncoder
-def split_package_details(request, name='', repo='', arch=''):
+def split_package_details(request, name, repo, arch):
arch = get_object_or_404(Arch, name=arch)
arches = [ arch ]
arches.extend(Arch.objects.filter(agnostic=True))
@@ -21,10 +24,10 @@ def split_package_details(request, name='', repo='', arch=''):
repo__testing=repo.testing, repo__staging=repo.staging,
arch__in=arches).order_by('pkgname')
if len(pkgs) == 0:
- raise Http404
+ return None
# we have packages, but ensure at least one is in the given repo
if not any(True for pkg in pkgs if pkg.repo == repo):
- raise Http404
+ return None
context = {
'list_title': 'Split Package Details',
'name': name,
@@ -35,6 +38,30 @@ def split_package_details(request, name='', repo='', arch=''):
context)
+CUTOFF = datetime.timedelta(days=60)
+
+
+def recently_removed_package(request, name, repo, arch, cutoff=CUTOFF):
+ '''We're just steps away from raising a 404, but check our packages update
+ table first to see if this package has existed in this repo before. If so,
+ we can show a 410 Gone page and point the requester in the right
+ direction.'''
+ arch = get_object_or_404(Arch, name=arch)
+ arches = [ arch ]
+ arches.extend(Arch.objects.filter(agnostic=True))
+ match = Update.objects.select_related('arch', 'repo').filter(
+ pkgname=name, repo__name__iexact=repo, arch__in=arches)
+ if cutoff is not None:
+ when = now() - cutoff
+ match = match.filter(created__gte=when)
+ try:
+ match = match.latest()
+ return render(request, 'packages/removed.html',
+ {'update': match, }, status=410)
+ except Update.DoesNotExist:
+ return None
+
+
def details(request, name='', repo='', arch=''):
if all([name, repo, arch]):
try:
@@ -54,7 +81,16 @@ def details(request, name='', repo='', arch=''):
repo__name__iexact=repo, arch__agnostic=True)
if len(pkgs) == 1:
return redirect(pkgs[0], permanent=True)
- return split_package_details(request, name, repo, arch)
+ # do we have a split package matching this criteria?
+ ret = split_package_details(request, name, repo, arch)
+ if ret is None:
+ # maybe we have a recently-removed package?
+ ret = recently_removed_package(request, name, repo, arch)
+ if ret is not None:
+ return ret
+ else:
+ # we've tried everything at this point, nothing to see
+ raise Http404
else:
pkg_data = [
('arch', arch.lower()),
diff --git a/templates/packages/removed.html b/templates/packages/removed.html
new file mode 100644
index 00000000..17b1f989
--- /dev/null
+++ b/templates/packages/removed.html
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+{% load url from future %}
+{% load package_extras %}
+
+{% block title %}Arch Linux - Not Available - {{ update.pkgname }} {{ update.old_version }} ({{ update.arch.name }}){% endblock %}
+{% block navbarclass %}anb-packages{% endblock %}
+
+{% block content %}
+
+
{{ update.pkgname }} {{ update.old_version }} is no longer available
+
+
{{ update.pkgname }} {{ update.old_version }} has been removed from the [{{ update.repo.name|lower }}] repository.
+
+ {% with update.elsewhere as elsewhere %}{% if elsewhere %}
+
However, this package is available in other repositories:
+
+ {% for pkg in elsewhere %}
+ - {% pkg_details_link pkg %} {{ pkg.full_version }} [{{ pkg.repo.name|lower }}] ({{ pkg.arch.name }})
+ {% endfor %}
+
+ {% else %}
+
Unfortunately, this package cannot be found in any other repositories.
+ Try using the package search page,
+ or try searching the AUR
+ to see if the package can be found there.
+ {% endif %}{% endwith %}
+
+{% endblock %}
--
cgit v1.2.3-54-g00ecf
From 374bf53505480eebd675e95f975dc908c485a6fa Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Mon, 23 Jul 2012 21:17:02 -0500
Subject: Remove files list AJAX conditionals
Now that we just generate this list in JS, we don't need this separate
code.
Signed-off-by: Dan McGee
---
packages/views/display.py | 4 ----
1 file changed, 4 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/display.py b/packages/views/display.py
index 5332dc13..d5aa2c20 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -7,7 +7,6 @@
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.timezone import now
from django.views.generic.simple import direct_to_template
-from django.views.decorators.vary import vary_on_headers
from main.models import Package, PackageFile, Arch, Repo
from mirrors.utils import get_mirror_url_for_download
@@ -132,7 +131,6 @@ def group_details(request, arch, name):
return direct_to_template(request, 'packages/packages_list.html', context)
-@vary_on_headers('X-Requested-With')
def files(request, name, repo, arch):
pkg = get_object_or_404(Package,
pkgname=name, repo__name__iexact=repo, arch__name=arch)
@@ -147,8 +145,6 @@ def files(request, name, repo, arch):
'dir_count': dir_count,
}
template = 'packages/files.html'
- if request.is_ajax():
- template = 'packages/files_list.html'
return direct_to_template(request, template, context)
--
cgit v1.2.3-54-g00ecf
From 211340c8bd6ccd6b16f3115a71fce4abedcc4c06 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Mon, 23 Jul 2012 21:31:17 -0500
Subject: Ensure package files JS can support corner cases
We should handle the cases dealing with no filelist available, outdated
filelist, or a package without files, just as the HTML server-side page
does. Add a bit more info to the JSON returned so we can do so.
Signed-off-by: Dan McGee
---
packages/views/display.py | 6 ++++++
sitestatic/archweb.js | 12 +++++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)
(limited to 'packages/views')
diff --git a/packages/views/display.py b/packages/views/display.py
index d5aa2c20..02f5a5b2 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -160,10 +160,16 @@ def files_json(request, name, repo, arch):
pkgname=name, repo__name__iexact=repo, arch__name=arch)
# files are inserted in sorted order, so preserve that
fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
+ dir_count = sum(1 for f in fileslist if f.is_directory)
+ files_count = len(fileslist) - dir_count
data = {
'pkgname': pkg.pkgname,
'repo': pkg.repo.name.lower(),
'arch': pkg.arch.name.lower(),
+ 'pkg_last_update': pkg.last_update,
+ 'files_last_update': pkg.files_last_update,
+ 'files_count': files_count,
+ 'dir_count': dir_count,
'files': fileslist,
}
to_json = json.dumps(data, ensure_ascii=False, cls=PackageJSONEncoder)
diff --git a/sitestatic/archweb.js b/sitestatic/archweb.js
index d17cc68f..b04b1d01 100644
--- a/sitestatic/archweb.js
+++ b/sitestatic/archweb.js
@@ -170,7 +170,17 @@ function ajaxifyFiles() {
var cls = value.match(/\/$/) ? 'd' : 'f';
return ['', value, ''];
});
- $('#pkgfilelist').html('' + list_items.join('') + '
');
+ $('#pkgfilelist').empty();
+ if (data.pkg_last_update > data.files_last_update) {
+ $('#pkgfilelist').append('Note: This file list was generated from a previous version of the package; it may be out of date.
');
+ }
+ if (list_items.length > 0) {
+ $('#pkgfilelist').append('' + list_items.join('') + '
');
+ } else if (data.files_last_update == null) {
+ $('#pkgfilelist').append('No file list available.
');
+ } else {
+ $('#pkgfilelist').append('Package has no files.
');
+ }
});
});
}
--
cgit v1.2.3-54-g00ecf
From 9ab460c53a1ac4c79da6f05f2850ee21beedbab2 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Mon, 23 Jul 2012 21:47:43 -0500
Subject: Fall back to 410 Gone for package files view as well
This is another thing that Google and other search engines try to crawl
that no longer exists at times, so we should handle it gracefully.
Signed-off-by: Dan McGee
---
packages/views/display.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/display.py b/packages/views/display.py
index 02f5a5b2..31f18c79 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -132,8 +132,16 @@ def group_details(request, arch, name):
def files(request, name, repo, arch):
- pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ try:
+ pkg = Package.objects.get(pkgname=name,
+ repo__name__iexact=repo, arch__name=arch)
+ except Package.DoesNotExist:
+ # this may have been deleted recently, so follow the same logic as we
+ # do on the package details page if possible
+ ret = recently_removed_package(request, name, repo, arch)
+ if ret is not None:
+ return ret
+ raise Http404
# files are inserted in sorted order, so preserve that
fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
dir_count = sum(1 for f in fileslist if f.is_directory)
--
cgit v1.2.3-54-g00ecf
From c0bf9e20660cfae7ea8994472555bba23398b598 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 24 Jul 2012 09:19:48 -0500
Subject: Remove custom utc_now() function, use django.utils.timezone.now()
This was around from the time when we handled timezones sanely and
Django did not; now that we are on 1.4 we no longer need our own code to
handle this.
Signed-off-by: Dan McGee
---
devel/management/commands/reporead.py | 9 +++++----
devel/models.py | 5 +++--
devel/views.py | 12 ++++++------
main/models.py | 5 +++--
main/utils.py | 9 ++-------
mirrors/management/commands/mirrorcheck.py | 7 ++++---
mirrors/utils.py | 17 +++++++++--------
news/models.py | 11 +++++------
packages/management/commands/signoff_report.py | 8 ++++----
packages/views/flag.py | 8 ++++----
packages/views/signoff.py | 4 ++--
releng/management/commands/syncisos.py | 5 ++---
12 files changed, 49 insertions(+), 51 deletions(-)
(limited to 'packages/views')
diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py
index 2d9b68b2..e69691db 100644
--- a/devel/management/commands/reporead.py
+++ b/devel/management/commands/reporead.py
@@ -28,10 +28,11 @@
from django.core.management.base import BaseCommand, CommandError
from django.db import connections, router, transaction
from django.db.utils import IntegrityError
+from django.utils.timezone import now
from devel.utils import UserFinder
from main.models import Arch, Package, PackageFile, Repo
-from main.utils import utc_now, database_vendor
+from main.utils import database_vendor
from packages.models import Depend, Conflict, Provision, Replacement, Update
@@ -318,7 +319,7 @@ def populate_files(dbpkg, repopkg, force=False):
filename=filename)
pkg_files.append(pkgfile)
batched_bulk_create(PackageFile, pkg_files)
- dbpkg.files_last_update = utc_now()
+ dbpkg.files_last_update = now()
dbpkg.save()
@@ -388,7 +389,7 @@ def db_update(archname, reponame, pkgs, force=False):
dbpkg = Package(pkgname=pkg.name, arch=architecture, repo=repository)
try:
with transaction.commit_on_success():
- populate_pkg(dbpkg, pkg, timestamp=utc_now())
+ populate_pkg(dbpkg, pkg, timestamp=now())
Update.objects.log_update(None, dbpkg)
except IntegrityError:
logger.warning("Could not add package %s; "
@@ -417,7 +418,7 @@ def db_update(archname, reponame, pkgs, force=False):
if not force and pkg_same_version(pkg, dbpkg):
continue
elif not force:
- timestamp = utc_now()
+ timestamp = now()
# The odd select_for_update song and dance here are to ensure
# simultaneous updates don't happen on a package, causing
diff --git a/devel/models.py b/devel/models.py
index fd5df00a..9b6f07a7 100644
--- a/devel/models.py
+++ b/devel/models.py
@@ -4,10 +4,11 @@
from django.db import models
from django.db.models.signals import pre_save
from django.contrib.auth.models import User
+from django.utils.timezone import now
from django_countries import CountryField
from .fields import PGPKeyField
-from main.utils import make_choice, utc_now
+from main.utils import make_choice
class UserProfile(models.Model):
@@ -105,7 +106,7 @@ def set_last_modified(sender, **kwargs):
signal handler.'''
obj = kwargs['instance']
if hasattr(obj, 'last_modified'):
- obj.last_modified = utc_now()
+ obj.last_modified = now()
# connect signals needed to keep cache in line with reality
diff --git a/devel/views.py b/devel/views.py
index 78ed26f2..143b12bf 100644
--- a/devel/views.py
+++ b/devel/views.py
@@ -24,11 +24,11 @@
from django.views.generic.simple import direct_to_template
from django.utils.encoding import force_unicode
from django.utils.http import http_date
+from django.utils.timezone import now
from .models import UserProfile
from main.models import Package, PackageFile, TodolistPkg
from main.models import Arch, Repo
-from main.utils import utc_now
from news.models import News
from packages.models import PackageRelation, Signoff, Depend
from packages.utils import get_signoff_groups
@@ -122,15 +122,15 @@ def clock(request):
else:
dev.last_action = None
- now = utc_now()
+ current_time = now()
page_dict = {
'developers': devs,
- 'utc_now': now,
+ 'utc_now': current_time,
}
response = direct_to_template(request, 'devel/clock.html', page_dict)
if not response.has_header('Expires'):
- expire_time = now.replace(second=0, microsecond=0)
+ expire_time = current_time.replace(second=0, microsecond=0)
expire_time += timedelta(minutes=1)
expire_time = time.mktime(expire_time.timetuple())
response['Expires'] = http_date(expire_time)
@@ -198,12 +198,12 @@ def report(request, report_name, username=None):
if report_name == 'old':
title = 'Packages last built more than one year ago'
- cutoff = utc_now() - timedelta(days=365)
+ cutoff = now() - timedelta(days=365)
packages = packages.filter(
build_date__lt=cutoff).order_by('build_date')
elif report_name == 'long-out-of-date':
title = 'Packages marked out-of-date more than 90 days ago'
- cutoff = utc_now() - timedelta(days=90)
+ cutoff = now() - timedelta(days=90)
packages = packages.filter(
flag_date__lt=cutoff).order_by('flag_date')
elif report_name == 'big':
diff --git a/main/models.py b/main/models.py
index 04d8da8f..6c9dfe4d 100644
--- a/main/models.py
+++ b/main/models.py
@@ -6,9 +6,10 @@
from django.db import models
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
+from django.utils.timezone import now
from .fields import PositiveBigIntegerField
-from .utils import cache_function, set_created_field, utc_now
+from .utils import cache_function, set_created_field
class TodolistManager(models.Manager):
@@ -385,7 +386,7 @@ class Meta:
def set_todolist_fields(sender, **kwargs):
todolist = kwargs['instance']
if not todolist.date_added:
- todolist.date_added = utc_now()
+ todolist.date_added = now()
# connect signals needed to keep cache in line with reality
from main.utils import refresh_latest
diff --git a/main/utils.py b/main/utils.py
index 879abfb9..0b6849a4 100644
--- a/main/utils.py
+++ b/main/utils.py
@@ -5,10 +5,10 @@
from datetime import datetime
import hashlib
-from pytz import utc
from django.core.cache import cache
from django.db import connections, router
+from django.utils.timezone import now
CACHE_TIMEOUT = 1800
@@ -94,17 +94,12 @@ def retrieve_latest(sender, latest_by=None):
return None
-def utc_now():
- '''Returns a timezone-aware UTC date representing now.'''
- return datetime.utcnow().replace(tzinfo=utc)
-
-
def set_created_field(sender, **kwargs):
'''This will set the 'created' field on any object to the current UTC time
if it is unset. For use as a pre_save signal handler.'''
obj = kwargs['instance']
if hasattr(obj, 'created') and not obj.created:
- obj.created = utc_now()
+ obj.created = now()
def database_vendor(model, mode='read'):
diff --git a/mirrors/management/commands/mirrorcheck.py b/mirrors/management/commands/mirrorcheck.py
index 7a133cbf..e09ea680 100644
--- a/mirrors/management/commands/mirrorcheck.py
+++ b/mirrors/management/commands/mirrorcheck.py
@@ -29,8 +29,9 @@
from django.core.management.base import NoArgsCommand
from django.db import transaction
+from django.utils.timezone import now
-from main.utils import utc_now, database_vendor
+from main.utils import database_vendor
from mirrors.models import MirrorUrl, MirrorLog
logging.basicConfig(
@@ -83,7 +84,7 @@ def parse_lastsync(log, data):
def check_mirror_url(mirror_url, timeout):
url = mirror_url.url + 'lastsync'
logger.info("checking URL %s", url)
- log = MirrorLog(url=mirror_url, check_time=utc_now())
+ log = MirrorLog(url=mirror_url, check_time=now())
headers = {'User-Agent': 'archweb/1.0'}
req = urllib2.Request(url, None, headers)
try:
@@ -136,7 +137,7 @@ def check_mirror_url(mirror_url, timeout):
def check_rsync_url(mirror_url, timeout):
url = mirror_url.url + 'lastsync'
logger.info("checking URL %s", url)
- log = MirrorLog(url=mirror_url, check_time=utc_now())
+ log = MirrorLog(url=mirror_url, check_time=now())
tempdir = tempfile.mkdtemp()
lastsync_path = os.path.join(tempdir, 'lastsync')
diff --git a/mirrors/utils.py b/mirrors/utils.py
index f2c98ee0..bf030d39 100644
--- a/mirrors/utils.py
+++ b/mirrors/utils.py
@@ -1,13 +1,14 @@
from datetime import timedelta
from django.db.models import Avg, Count, Max, Min, StdDev
+from django.utils.timezone import now
from django_countries.fields import Country
-from main.utils import cache_function, utc_now, database_vendor
+from main.utils import cache_function, database_vendor
from .models import MirrorLog, MirrorProtocol, MirrorUrl
-default_cutoff = timedelta(hours=24)
+DEFAULT_CUTOFF = timedelta(hours=24)
def annotate_url(url, delays):
'''Given a MirrorURL object, add a few more attributes to it regarding
@@ -30,8 +31,8 @@ def annotate_url(url, delays):
@cache_function(123)
-def get_mirror_statuses(cutoff=default_cutoff):
- cutoff_time = utc_now() - cutoff
+def get_mirror_statuses(cutoff=DEFAULT_CUTOFF):
+ cutoff_time = now() - cutoff
# I swear, this actually has decent performance...
urls = MirrorUrl.objects.select_related('mirror', 'protocol').filter(
mirror__active=True, mirror__public=True,
@@ -88,8 +89,8 @@ def get_mirror_statuses(cutoff=default_cutoff):
@cache_function(117)
-def get_mirror_errors(cutoff=default_cutoff):
- cutoff_time = utc_now() - cutoff
+def get_mirror_errors(cutoff=DEFAULT_CUTOFF):
+ cutoff_time = now() - cutoff
errors = MirrorLog.objects.filter(
is_success=False, check_time__gte=cutoff_time,
url__mirror__active=True, url__mirror__public=True).values(
@@ -105,11 +106,11 @@ def get_mirror_errors(cutoff=default_cutoff):
@cache_function(295)
-def get_mirror_url_for_download(cutoff=default_cutoff):
+def get_mirror_url_for_download(cutoff=DEFAULT_CUTOFF):
'''Find a good mirror URL to use for package downloads. If we have mirror
status data available, it is used to determine a good choice by looking at
the last batch of status rows.'''
- cutoff_time = utc_now() - cutoff
+ cutoff_time = now() - cutoff
status_data = MirrorLog.objects.filter(
check_time__gte=cutoff_time).aggregate(
Max('check_time'), Max('last_sync'))
diff --git a/news/models.py b/news/models.py
index 95026e1d..2efea579 100644
--- a/news/models.py
+++ b/news/models.py
@@ -1,8 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
-
-from main.utils import utc_now
+from django.utils.timezone import now
class News(models.Model):
@@ -29,13 +28,13 @@ class Meta:
def set_news_fields(sender, **kwargs):
news = kwargs['instance']
- now = utc_now()
- news.last_modified = now
+ current_time = now()
+ news.last_modified = current_time
if not news.postdate:
- news.postdate = now
+ news.postdate = current_time
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
news.guid = 'tag:%s,%s:%s' % (Site.objects.get_current(),
- now.strftime('%Y-%m-%d'), news.get_absolute_url())
+ current_time.strftime('%Y-%m-%d'), news.get_absolute_url())
# connect signals needed to keep cache in line with reality
from main.utils import refresh_latest
diff --git a/packages/management/commands/signoff_report.py b/packages/management/commands/signoff_report.py
index ddf930db..72fcbe1e 100644
--- a/packages/management/commands/signoff_report.py
+++ b/packages/management/commands/signoff_report.py
@@ -15,6 +15,7 @@
from django.contrib.sites.models import Site
from django.db.models import Count
from django.template import loader, Context
+from django.utils.timezone import now
from collections import namedtuple
from datetime import timedelta
@@ -23,7 +24,6 @@
import sys
from main.models import Repo
-from main.utils import utc_now
from packages.models import Signoff
from packages.utils import get_signoff_groups
@@ -66,9 +66,9 @@ def generate_report(email, repo_name):
new_hours = 24
old_days = 14
- now = utc_now()
- new_cutoff = now - timedelta(hours=new_hours)
- old_cutoff = now - timedelta(days=old_days)
+ current_time = now()
+ new_cutoff = current_time - timedelta(hours=new_hours)
+ old_cutoff = current_time - timedelta(days=old_days)
if len(signoff_groups) == 0:
# no need to send an email at all
diff --git a/packages/views/flag.py b/packages/views/flag.py
index 7fa2d508..f3db93b3 100644
--- a/packages/views/flag.py
+++ b/packages/views/flag.py
@@ -5,12 +5,12 @@
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect
from django.template import loader, Context
+from django.utils.timezone import now
from django.views.generic.simple import direct_to_template
from django.views.decorators.cache import cache_page, never_cache
from ..models import FlagRequest
from main.models import Package
-from main.utils import utc_now
class FlagForm(forms.Form):
@@ -76,10 +76,10 @@ def flag(request, name, repo, arch):
@transaction.commit_on_success
def perform_updates():
- now = utc_now()
- pkgs.update(flag_date=now)
+ current_time = now()
+ pkgs.update(flag_date=current_time)
# store our flag request
- flag_request = FlagRequest(created=now,
+ flag_request = FlagRequest(created=current_time,
user_email=email, message=message,
ip_address=ip_addr, pkgbase=pkg.pkgbase,
version=version, repo=pkg.repo,
diff --git a/packages/views/signoff.py b/packages/views/signoff.py
index 61d949fc..7aa39106 100644
--- a/packages/views/signoff.py
+++ b/packages/views/signoff.py
@@ -8,11 +8,11 @@
from django.db import transaction
from django.http import HttpResponse, Http404
from django.shortcuts import get_list_or_404, redirect, render
+from django.utils.timezone import now
from django.views.decorators.cache import never_cache
from django.views.generic.simple import direct_to_template
from main.models import Package, Arch, Repo
-from main.utils import utc_now
from ..models import SignoffSpecification, Signoff
from ..utils import (get_signoff_groups, approved_by_signoffs,
PackageSignoffGroup)
@@ -45,7 +45,7 @@ def signoff_package(request, name, repo, arch, revoke=False):
package, request.user, False)
except Signoff.DoesNotExist:
raise Http404
- signoff.revoked = utc_now()
+ signoff.revoked = now()
signoff.save()
created = False
else:
diff --git a/releng/management/commands/syncisos.py b/releng/management/commands/syncisos.py
index 62f005ff..223c771b 100644
--- a/releng/management/commands/syncisos.py
+++ b/releng/management/commands/syncisos.py
@@ -4,8 +4,8 @@
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
+from django.utils.timezone import now
-from main.utils import utc_now
from releng.models import Iso
@@ -54,9 +54,8 @@ def handle(self, *args, **options):
existing.active = True
existing.removed = None
existing.save()
- now = utc_now()
# and then mark all other names as no longer active
Iso.objects.filter(active=True).exclude(name__in=active_isos).update(
- active=False, removed=now)
+ active=False, removed=now())
# vim: set ts=4 sw=4 et:
--
cgit v1.2.3-54-g00ecf
From 76c37ce3acc7a4af0271c7535d4a33042f7749b5 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 24 Jul 2012 09:35:55 -0500
Subject: Replace deprecated direct_to_template() with render() shortcut
Now that Django actually provides a concise way to use a RequestContext
object without instantiating it, we can use that rather than the old
function-based generic view that worked well to do the same.
Additionally, these function-based generic views will be gone in Django
1.5, so might as well make the move now.
Signed-off-by: Dan McGee
---
devel/views.py | 15 +++++++--------
mirrors/views.py | 19 +++++++++----------
packages/views/__init__.py | 11 +++++------
packages/views/display.py | 13 +++++--------
packages/views/flag.py | 12 +++++-------
packages/views/signoff.py | 5 ++---
public/views.py | 14 +++++++-------
releng/views.py | 15 +++++++--------
retro/views.py | 4 ++--
todolists/views.py | 13 ++++++-------
visualize/views.py | 4 ++--
11 files changed, 57 insertions(+), 68 deletions(-)
(limited to 'packages/views')
diff --git a/devel/views.py b/devel/views.py
index 143b12bf..f877bc84 100644
--- a/devel/views.py
+++ b/devel/views.py
@@ -17,11 +17,10 @@
from django.db import transaction
from django.db.models import F, Count, Max
from django.http import Http404
-from django.shortcuts import get_object_or_404
+from django.shortcuts import get_object_or_404, render
from django.template import loader, Context
from django.template.defaultfilters import filesizeformat
from django.views.decorators.cache import never_cache
-from django.views.generic.simple import direct_to_template
from django.utils.encoding import force_unicode
from django.utils.http import http_date
from django.utils.timezone import now
@@ -88,7 +87,7 @@ def index(request):
'signoffs': signoffs
}
- return direct_to_template(request, 'devel/index.html', page_dict)
+ return render(request, 'devel/index.html', page_dict)
@login_required
def clock(request):
@@ -128,7 +127,7 @@ def clock(request):
'utc_now': current_time,
}
- response = direct_to_template(request, 'devel/clock.html', page_dict)
+ response = render(request, 'devel/clock.html', page_dict)
if not response.has_header('Expires'):
expire_time = current_time.replace(second=0, microsecond=0)
expire_time += timedelta(minutes=1)
@@ -178,7 +177,7 @@ def change_profile(request):
else:
form = ProfileForm(initial={'email': request.user.email})
profile_form = UserProfileForm(instance=request.user.get_profile())
- return direct_to_template(request, 'devel/profile.html',
+ return render(request, 'devel/profile.html',
{'form': form, 'profile_form': profile_form})
@login_required
@@ -301,7 +300,7 @@ def report(request, report_name, username=None):
'column_names': names,
'column_attrs': attrs,
}
- return direct_to_template(request, 'devel/packages.html', context)
+ return render(request, 'devel/packages.html', context)
class NewUserForm(forms.ModelForm):
@@ -399,7 +398,7 @@ def inner_save():
'title': 'Create User',
'submit_text': 'Create User'
}
- return direct_to_template(request, 'general_form.html', context)
+ return render(request, 'general_form.html', context)
@user_passes_test(lambda u: u.is_superuser)
def admin_log(request, username=None):
@@ -410,6 +409,6 @@ def admin_log(request, username=None):
'title': "Admin Action Log",
'log_user': user,
}
- return direct_to_template(request, 'devel/admin_log.html', context)
+ return render(request, 'devel/admin_log.html', context)
# vim: set ts=4 sw=4 et:
diff --git a/mirrors/views.py b/mirrors/views.py
index 8f092be7..400c084d 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -8,9 +8,8 @@
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Q
from django.http import Http404, HttpResponse
-from django.shortcuts import get_object_or_404
+from django.shortcuts import get_object_or_404, render
from django.views.decorators.csrf import csrf_exempt
-from django.views.generic.simple import direct_to_template
from django_countries.countries import COUNTRIES
from .models import Mirror, MirrorUrl, MirrorProtocol, TIER_CHOICES
@@ -76,7 +75,7 @@ def generate_mirrorlist(request):
else:
form = MirrorlistForm()
- return direct_to_template(request, 'mirrors/mirrorlist_generate.html',
+ return render(request, 'mirrors/mirrorlist_generate.html',
{'mirrorlist_form': form})
@@ -142,10 +141,10 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False,
urls = status_filter(urls)
template = 'mirrors/mirrorlist_status.txt'
- return direct_to_template(request, template, {
- 'mirror_urls': urls,
- },
- mimetype='text/plain')
+ context = {
+ 'mirror_urls': urls,
+ }
+ return render(request, template, context, content_type='text/plain')
def find_mirrors_simple(request, protocol):
@@ -161,7 +160,7 @@ def mirrors(request):
mirror_list = Mirror.objects.select_related().order_by('tier', 'country')
if not request.user.is_authenticated():
mirror_list = mirror_list.filter(public=True, active=True)
- return direct_to_template(request, 'mirrors/mirrors.html',
+ return render(request, 'mirrors/mirrors.html',
{'mirror_list': mirror_list})
@@ -180,7 +179,7 @@ def mirror_details(request, name):
all_urls = set(checked_urls).union(all_urls)
all_urls = sorted(all_urls, key=attrgetter('url'))
- return direct_to_template(request, 'mirrors/mirror_details.html',
+ return render(request, 'mirrors/mirror_details.html',
{'mirror': mirror, 'urls': all_urls})
@@ -217,7 +216,7 @@ def status(request, tier=None):
'error_logs': error_logs,
'tier': tier,
})
- return direct_to_template(request, 'mirrors/status.html', context)
+ return render(request, 'mirrors/status.html', context)
class MirrorStatusJSONEncoder(DjangoJSONEncoder):
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index fa67daa8..19ea9103 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -6,10 +6,9 @@
from django.contrib.auth.models import User
from django.core.cache import cache
from django.http import HttpResponse
-from django.shortcuts import redirect
+from django.shortcuts import redirect, render
from django.views.decorators.cache import cache_control
from django.views.decorators.http import require_GET, require_POST
-from django.views.generic.simple import direct_to_template
from main.models import Package, Arch
from ..models import PackageRelation
@@ -32,9 +31,9 @@ def opensearch(request):
else:
domain = "http://%s" % request.META['HTTP_HOST']
- return direct_to_template(request, 'packages/opensearch.xml',
+ return render(request, 'packages/opensearch.xml',
{'domain': domain},
- mimetype='application/opensearchdescription+xml')
+ content_type='application/opensearchdescription+xml')
@require_GET
@@ -115,7 +114,7 @@ def arch_differences(request):
'differences': differences,
'multilib_differences': multilib_diffs
}
- return direct_to_template(request, 'packages/differences.html', context)
+ return render(request, 'packages/differences.html', context)
@permission_required('main.change_package')
def stale_relations(request):
@@ -132,7 +131,7 @@ def stale_relations(request):
'missing_pkgbase': missing_pkgbase,
'wrong_permissions': wrong_permissions,
}
- return direct_to_template(request, 'packages/stale_relations.html', context)
+ return render(request, 'packages/stale_relations.html', context)
@permission_required('packages.delete_packagerelation')
@require_POST
diff --git a/packages/views/display.py b/packages/views/display.py
index 31f18c79..585e0e4e 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -6,7 +6,6 @@
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.timezone import now
-from django.views.generic.simple import direct_to_template
from main.models import Package, PackageFile, Arch, Repo
from mirrors.utils import get_mirror_url_for_download
@@ -33,8 +32,7 @@ def split_package_details(request, name, repo, arch):
'arch': arch,
'packages': pkgs,
}
- return direct_to_template(request, 'packages/packages_list.html',
- context)
+ return render(request, 'packages/packages_list.html', context)
CUTOFF = datetime.timedelta(days=60)
@@ -67,8 +65,7 @@ def details(request, name='', repo='', arch=''):
pkg = Package.objects.select_related(
'arch', 'repo', 'packager').get(pkgname=name,
repo__name__iexact=repo, arch__name=arch)
- return direct_to_template(request, 'packages/details.html',
- {'pkg': pkg, })
+ return render(request, 'packages/details.html', {'pkg': pkg})
except Package.DoesNotExist:
arch_obj = get_object_or_404(Arch, name=arch)
# for arch='any' packages, we can issue a redirect to them if we
@@ -111,7 +108,7 @@ def groups(request, arch=None):
'groups': grps,
'arch': arch,
}
- return direct_to_template(request, 'packages/groups.html', context)
+ return render(request, 'packages/groups.html', context)
def group_details(request, arch, name):
@@ -128,7 +125,7 @@ def group_details(request, arch, name):
'arch': arch,
'packages': pkgs,
}
- return direct_to_template(request, 'packages/packages_list.html', context)
+ return render(request, 'packages/packages_list.html', context)
def files(request, name, repo, arch):
@@ -153,7 +150,7 @@ def files(request, name, repo, arch):
'dir_count': dir_count,
}
template = 'packages/files.html'
- return direct_to_template(request, template, context)
+ return render(request, template, context)
def details_json(request, name, repo, arch):
diff --git a/packages/views/flag.py b/packages/views/flag.py
index f3db93b3..b9542a62 100644
--- a/packages/views/flag.py
+++ b/packages/views/flag.py
@@ -3,10 +3,9 @@
from django.contrib.auth.decorators import permission_required
from django.core.mail import send_mail
from django.db import transaction
-from django.shortcuts import get_object_or_404, redirect
+from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader, Context
from django.utils.timezone import now
-from django.views.generic.simple import direct_to_template
from django.views.decorators.cache import cache_page, never_cache
from ..models import FlagRequest
@@ -34,7 +33,7 @@ def __init__(self, *args, **kwargs):
@cache_page(3600)
def flaghelp(request):
- return direct_to_template(request, 'packages/flaghelp.html')
+ return render(request, 'packages/flaghelp.html')
@never_cache
@@ -43,8 +42,7 @@ def flag(request, name, repo, arch):
pkgname=name, repo__name__iexact=repo, arch__name=arch)
if pkg.flag_date is not None:
# already flagged. do nothing.
- return direct_to_template(request, 'packages/flagged.html',
- {'pkg': pkg})
+ return render(request, 'packages/flagged.html', {'pkg': pkg})
# find all packages from (hopefully) the same PKGBUILD
pkgs = Package.objects.normal().filter(
pkgbase=pkg.pkgbase, flag_date__isnull=True,
@@ -129,7 +127,7 @@ def perform_updates():
'packages': pkgs,
'form': form
}
- return direct_to_template(request, 'packages/flag.html', context)
+ return render(request, 'packages/flag.html', context)
def flag_confirmed(request, name, repo, arch):
pkg = get_object_or_404(Package,
@@ -142,7 +140,7 @@ def flag_confirmed(request, name, repo, arch):
context = {'package': pkg, 'packages': pkgs}
- return direct_to_template(request, 'packages/flag_confirmed.html', context)
+ return render(request, 'packages/flag_confirmed.html', context)
@permission_required('main.change_package')
def unflag(request, name, repo, arch):
diff --git a/packages/views/signoff.py b/packages/views/signoff.py
index 7aa39106..56eb060c 100644
--- a/packages/views/signoff.py
+++ b/packages/views/signoff.py
@@ -10,7 +10,6 @@
from django.shortcuts import get_list_or_404, redirect, render
from django.utils.timezone import now
from django.views.decorators.cache import never_cache
-from django.views.generic.simple import direct_to_template
from main.models import Package, Arch, Repo
from ..models import SignoffSpecification, Signoff
@@ -28,7 +27,7 @@ def signoffs(request):
'arches': Arch.objects.all(),
'repo_names': sorted(set(g.target_repo for g in signoff_groups)),
}
- return direct_to_template(request, 'packages/signoffs.html', context)
+ return render(request, 'packages/signoffs.html', context)
@permission_required('main.change_package')
@never_cache
@@ -144,7 +143,7 @@ def signoff_options(request, name, repo, arch):
'package': package,
'form': form,
}
- return direct_to_template(request, 'packages/signoff_options.html', context)
+ return render(request, 'packages/signoff_options.html', context)
class SignoffJSONEncoder(DjangoJSONEncoder):
'''Base JSONEncoder extended to handle all serialization of all classes
diff --git a/public/views.py b/public/views.py
index 3ea8f841..3f68545c 100644
--- a/public/views.py
+++ b/public/views.py
@@ -5,8 +5,8 @@
from django.contrib.auth.models import User
from django.db.models import Count, Q
from django.http import Http404
+from django.shortcuts import render
from django.views.decorators.cache import cache_control
-from django.views.generic.simple import direct_to_template
from devel.models import MasterKey, PGPSignature
from main.models import Arch, Repo, Donor
@@ -21,7 +21,7 @@ def index(request):
'news_updates': News.objects.order_by('-postdate', '-id')[:15],
'pkg_updates': pkgs,
}
- return direct_to_template(request, 'public/index.html', context)
+ return render(request, 'public/index.html', context)
USER_LISTS = {
'devs': {
@@ -55,14 +55,14 @@ def userlist(request, user_type='devs'):
users = users.distinct()
context = USER_LISTS[user_type].copy()
context['users'] = users
- return direct_to_template(request, 'public/userlist.html', context)
+ return render(request, 'public/userlist.html', context)
@cache_control(max_age=300)
def donate(request):
context = {
'donors': Donor.objects.filter(visible=True).order_by('name'),
}
- return direct_to_template(request, 'public/donate.html', context)
+ return render(request, 'public/donate.html', context)
@cache_control(max_age=300)
def download(request):
@@ -76,7 +76,7 @@ def download(request):
'releng_pxeboot_url': settings.PXEBOOT_URL,
'mirror_urls': mirror_urls,
}
- return direct_to_template(request, 'public/download.html', context)
+ return render(request, 'public/download.html', context)
@cache_control(max_age=300)
def feeds(request):
@@ -84,7 +84,7 @@ def feeds(request):
'arches': Arch.objects.all(),
'repos': Repo.objects.all(),
}
- return direct_to_template(request, 'public/feeds.html', context)
+ return render(request, 'public/feeds.html', context)
@cache_control(max_age=300)
def keys(request):
@@ -113,6 +113,6 @@ def keys(request):
'active_users': users,
'signatures': signatures,
}
- return direct_to_template(request, 'public/keys.html', context)
+ return render(request, 'public/keys.html', context)
# vim: set ts=4 sw=4 et:
diff --git a/releng/views.py b/releng/views.py
index fc81d410..a1bc3b81 100644
--- a/releng/views.py
+++ b/releng/views.py
@@ -2,8 +2,7 @@
from django.conf import settings
from django.db.models import Count, Max
from django.http import Http404
-from django.shortcuts import get_object_or_404, redirect
-from django.views.generic.simple import direct_to_template
+from django.shortcuts import get_object_or_404, redirect, render
from .models import (Architecture, BootType, Bootloader, ClockChoice,
Filesystem, HardwareType, InstallType, Iso, IsoType, Module, Source,
@@ -73,7 +72,7 @@ def submit_test_result(request):
form = TestForm()
context = {'form': form}
- return direct_to_template(request, 'releng/add.html', context)
+ return render(request, 'releng/add.html', context)
def calculate_option_overview(field_name):
field = Test._meta.get_field(field_name)
@@ -145,7 +144,7 @@ def test_results_overview(request):
'options': all_options,
'iso_url': settings.ISO_LIST_URL,
}
- return direct_to_template(request, 'releng/results.html', context)
+ return render(request, 'releng/results.html', context)
def test_results_iso(request, iso_id):
iso = get_object_or_404(Iso, pk=iso_id)
@@ -154,7 +153,7 @@ def test_results_iso(request, iso_id):
'iso_name': iso.name,
'test_list': test_list
}
- return direct_to_template(request, 'releng/result_list.html', context)
+ return render(request, 'releng/result_list.html', context)
def test_results_for(request, option, value):
if option not in Test._meta.get_all_field_names():
@@ -170,10 +169,10 @@ def test_results_for(request, option, value):
'value_id': value,
'test_list': test_list
}
- return direct_to_template(request, 'releng/result_list.html', context)
+ return render(request, 'releng/result_list.html', context)
def submit_test_thanks(request):
- return direct_to_template(request, "releng/thanks.html", None)
+ return render(request, "releng/thanks.html", None)
def iso_overview(request):
isos = Iso.objects.all().order_by('-pk')
@@ -192,6 +191,6 @@ def iso_overview(request):
context = {
'isos': isos
}
- return direct_to_template(request, 'releng/iso_overview.html', context)
+ return render(request, 'releng/iso_overview.html', context)
# vim: set ts=4 sw=4 et:
diff --git a/retro/views.py b/retro/views.py
index 3bc59e9f..31226deb 100644
--- a/retro/views.py
+++ b/retro/views.py
@@ -1,6 +1,6 @@
from django.http import Http404
+from django.shortcuts import render
from django.views.decorators.cache import cache_page
-from django.views.generic.simple import direct_to_template
RETRO_YEAR_MAP = {
@@ -26,6 +26,6 @@ def retro_homepage(request, year):
context = {
'year': year,
}
- return direct_to_template(request, 'retro/%s' % template, context)
+ return render(request, 'retro/%s' % template, context)
# vim: set ts=4 sw=4 et:
diff --git a/todolists/views.py b/todolists/views.py
index 580ec00f..c7ba2560 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -3,12 +3,11 @@
from django import forms
from django.http import HttpResponse
from django.core.mail import send_mail
-from django.shortcuts import get_list_or_404, get_object_or_404, redirect
+from django.shortcuts import get_list_or_404, get_object_or_404, redirect, render
from django.contrib.auth.decorators import login_required, permission_required
from django.db import transaction
from django.views.decorators.cache import never_cache
from django.views.generic import DeleteView
-from django.views.generic.simple import direct_to_template
from django.template import Context, loader
from main.models import Todolist, TodolistPkg, Package, Repo
@@ -54,7 +53,7 @@ def view(request, list_id):
# we don't hold onto the result, but the objects are the same here,
# so accessing maintainers in the template is now cheap
attach_maintainers(tp.pkg for tp in todolist.packages)
- return direct_to_template(request, 'todolists/view.html', {
+ return render(request, 'todolists/view.html', {
'list': todolist,
'svn_roots': svn_roots,
})
@@ -72,7 +71,7 @@ def list_pkgbases(request, list_id, svn_root):
@login_required
def todolist_list(request):
lists = get_annotated_todolists()
- return direct_to_template(request, 'todolists/list.html', {'lists': lists})
+ return render(request, 'todolists/list.html', {'lists': lists})
@permission_required('main.add_todolist')
@never_cache
@@ -92,7 +91,7 @@ def add(request):
'form': form,
'submit_text': 'Create List'
}
- return direct_to_template(request, 'general_form.html', page_dict)
+ return render(request, 'general_form.html', page_dict)
# TODO: this calls for transaction management and async emailing
@permission_required('main.change_todolist')
@@ -115,7 +114,7 @@ def edit(request, list_id):
'form': form,
'submit_text': 'Save List'
}
- return direct_to_template(request, 'general_form.html', page_dict)
+ return render(request, 'general_form.html', page_dict)
class DeleteTodolist(DeleteView):
model = Todolist
@@ -185,7 +184,7 @@ def public_list(request):
# total hackjob, but it makes this a lot less query-intensive.
all_pkgs = [tp for tl in todo_lists for tp in tl.packages]
attach_maintainers([tp.pkg for tp in all_pkgs])
- return direct_to_template(request, "todolists/public_list.html",
+ return render(request, "todolists/public_list.html",
{"todo_lists": todo_lists})
# vim: set ts=4 sw=4 et:
diff --git a/visualize/views.py b/visualize/views.py
index 95f8c314..44e60472 100644
--- a/visualize/views.py
+++ b/visualize/views.py
@@ -4,14 +4,14 @@
from django.contrib.auth.models import User
from django.db.models import Count, Sum, Q
from django.http import HttpResponse
+from django.shortcuts import render
from django.views.decorators.cache import cache_page
-from django.views.generic.simple import direct_to_template
from main.models import Package, Arch, Repo
from devel.models import MasterKey, PGPSignature
def index(request):
- return direct_to_template(request, 'visualize/index.html', {})
+ return render(request, 'visualize/index.html')
def arch_repo_data():
qs = Package.objects.select_related().values(
--
cgit v1.2.3-54-g00ecf
From 24b28a504cabcf077882aa95cfa0edbc6a8d4569 Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 24 Jul 2012 21:01:31 -0500
Subject: Replace deprecated list_detail usage in search with class-based view
We can convert the entire search view to a generic class-based ListView.
This is still one of the more disgusting views in the application and
has a ton of logic scattered buckshot across several methods, but this
commit is not meant to address all of that in one go.
This is the last of the deprecated pieces I know of we are still using
in the codebase, so we should be relatively safe in the long run now for
an upgrade to the eventual next major Django release.
Signed-off-by: Dan McGee
---
packages/urls.py | 8 +++--
packages/views/__init__.py | 2 +-
packages/views/search.py | 77 +++++++++++++++++++++++-----------------------
3 files changed, 45 insertions(+), 42 deletions(-)
(limited to 'packages/views')
diff --git a/packages/urls.py b/packages/urls.py
index 6eddc5fe..9a151b4b 100644
--- a/packages/urls.py
+++ b/packages/urls.py
@@ -1,5 +1,7 @@
from django.conf.urls import include, patterns
+from .views.search import SearchListView
+
package_patterns = patterns('packages.views',
(r'^$', 'details'),
(r'^json/$', 'details_json'),
@@ -21,9 +23,9 @@
(r'^signoffs/json/$', 'signoffs_json', {}, 'package-signoffs-json'),
(r'^update/$', 'update'),
- (r'^$', 'search', {}, 'packages-search'),
- (r'^search/json/$', 'search_json'),
- (r'^(?P\d+)/$', 'search'),
+ (r'^$', SearchListView.as_view(), {}, 'packages-search'),
+ (r'^(?P\d+)/$', SearchListView.as_view()),
+ (r'^search/json/$', 'search_json'),
(r'^differences/$', 'arch_differences', {}, 'packages-differences'),
(r'^stale_relations/$', 'stale_relations'),
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 19ea9103..038d40ac 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -19,7 +19,7 @@
from .display import (details, groups, group_details, files, details_json,
files_json, download)
from .flag import flaghelp, flag, flag_confirmed, unflag, unflag_all
-from .search import search, search_json
+from .search import search_json
from .signoff import signoffs, signoff_package, signoff_options, signoffs_json
diff --git a/packages/views/search.py b/packages/views/search.py
index a89822be..9750894a 100644
--- a/packages/views/search.py
+++ b/packages/views/search.py
@@ -6,7 +6,7 @@
from django.contrib.auth.models import User
from django.db.models import Q
from django.http import HttpResponse
-from django.views.generic import list_detail
+from django.views.generic import ListView
from main.models import Package, Arch, Repo
from main.utils import make_choice
@@ -33,6 +33,7 @@ def valid_value(self, value):
except (ValueError, TypeError):
return False
+
class PackageSearchForm(forms.Form):
repo = forms.MultipleChoiceField(required=False)
arch = forms.MultipleChoiceField(required=False)
@@ -69,6 +70,7 @@ def __init__(self, *args, **kwargs):
[('', 'All'), ('unknown', 'Unknown')] + \
[(m.username, m.get_full_name()) for m in maints]
+
def parse_form(form, packages):
if form.cleaned_data['repo']:
packages = packages.filter(
@@ -117,48 +119,47 @@ def parse_form(form, packages):
return packages
-def search(request, page=None):
- limit = 50
- sort = None
- packages = Package.objects.normal()
- if request.GET:
- form = PackageSearchForm(data=request.GET)
- if form.is_valid():
- packages = parse_form(form, packages)
- asked_limit = form.cleaned_data['limit']
+class SearchListView(ListView):
+ template_name = "packages/search.html"
+
+ sort_fields = ("arch", "repo", "pkgname", "pkgbase", "compressed_size",
+ "installed_size", "build_date", "last_update", "flag_date")
+ allowed_sort = list(sort_fields) + ["-" + s for s in sort_fields]
+
+ def get(self, request, *args, **kwargs):
+ self.form = PackageSearchForm(data=request.GET)
+ return super(SearchListView, self).get(request, *args, **kwargs)
+
+ def get_queryset(self):
+ packages = Package.objects.normal()
+ if self.form.is_valid():
+ packages = parse_form(self.form, packages)
+ sort = self.form.cleaned_data['sort']
+ if sort in self.allowed_sort:
+ packages = packages.order_by(sort)
+ else:
+ packages = packages.order_by('pkgname')
+ return packages
+
+ # Form had errors so don't return any results
+ return Package.objects.none()
+
+ def get_paginate_by(self, queryset):
+ limit = 50
+ if self.form.is_valid():
+ asked_limit = self.form.cleaned_data['limit']
if asked_limit and asked_limit < 0:
limit = None
elif asked_limit:
limit = asked_limit
- sort = form.cleaned_data['sort']
- else:
- # Form had errors, don't return any results, just the busted form
- packages = Package.objects.none()
- else:
- form = PackageSearchForm()
-
- current_query = request.GET.urlencode()
- page_dict = {
- 'search_form': form,
- 'current_query': current_query
- }
- allowed_sort = ["arch", "repo", "pkgname", "pkgbase",
- "compressed_size", "installed_size",
- "build_date", "last_update", "flag_date"]
- allowed_sort += ["-" + s for s in allowed_sort]
- if sort in allowed_sort:
- packages = packages.order_by(sort)
- page_dict['sort'] = sort
- else:
- packages = packages.order_by('pkgname')
-
- return list_detail.object_list(request, packages,
- template_name="packages/search.html",
- page=page,
- paginate_by=limit,
- template_object_name="package",
- extra_context=page_dict)
+ return limit
+
+ def get_context_data(self, **kwargs):
+ context = super(SearchListView, self).get_context_data(**kwargs)
+ context['current_query'] = self.request.GET.urlencode()
+ context['search_form'] = self.form
+ return context
def search_json(request):
--
cgit v1.2.3-54-g00ecf
From 4ad43fd8165834b26914ff8ba0666ce96267205b Mon Sep 17 00:00:00 2001
From: Dan McGee
Date: Tue, 31 Jul 2012 00:25:19 -0500
Subject: Fix broken hidden input sort field on search form
Signed-off-by: Dan McGee
---
packages/views/search.py | 2 +-
templates/packages/search.html | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'packages/views')
diff --git a/packages/views/search.py b/packages/views/search.py
index 9750894a..497d9bca 100644
--- a/packages/views/search.py
+++ b/packages/views/search.py
@@ -40,7 +40,7 @@ class PackageSearchForm(forms.Form):
name = forms.CharField(required=False)
desc = forms.CharField(required=False)
q = forms.CharField(required=False)
- sort = forms.CharField(required=False)
+ sort = forms.CharField(required=False, widget=forms.HiddenInput())
maintainer = forms.ChoiceField(required=False)
packager = forms.ChoiceField(required=False)
last_update = forms.DateField(required=False, widget=AdminDateWidget(),
diff --git a/templates/packages/search.html b/templates/packages/search.html
index 9d86cedf..ab9b6d32 100644
--- a/templates/packages/search.html
+++ b/templates/packages/search.html
@@ -19,7 +19,7 @@ Package Database
Package Search