From dc9dedaeb075630fa284036fb2f39de3c69004f9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 14 Jun 2011 19:10:16 -0500 Subject: Add JSON package details and files views These are retrieved by adding 'json/' to the normal package details or files view. Signed-off-by: Dan McGee --- packages/urls.py | 3 ++- packages/views.py | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 11 deletions(-) (limited to 'packages') diff --git a/packages/urls.py b/packages/urls.py index e0362fa2..3c2c87b0 100644 --- a/packages/urls.py +++ b/packages/urls.py @@ -2,8 +2,9 @@ package_patterns = patterns('packages.views', (r'^$', 'details'), + (r'^json/$', 'details_json'), (r'^files/$', 'files'), - (r'^maintainer/$', 'getmaintainer'), + (r'^files/json/$', 'files_json'), (r'^flag/$', 'flag'), (r'^flag/done/$', 'flag_confirmed', {}, 'package-flag-confirmed'), (r'^unflag/$', 'unflag'), diff --git a/packages/views.py b/packages/views.py index 23797f71..44a1db96 100644 --- a/packages/views.py +++ b/packages/views.py @@ -5,6 +5,7 @@ from django.contrib.auth.decorators import permission_required from django.conf import settings from django.core.mail import send_mail +from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Q from django.http import HttpResponse, Http404 from django.shortcuts import get_object_or_404, redirect @@ -24,9 +25,30 @@ from main.models import Arch, Repo, Signoff from main.utils import make_choice from mirrors.models import MirrorUrl -from .models import PackageRelation +from .models import PackageRelation, PackageGroup from .utils import get_group_info, get_differences_info, get_wrong_permissions +class PackageJSONEncoder(DjangoJSONEncoder): + pkg_attributes = [ 'pkgname', 'pkgbase', 'repo', 'arch', 'pkgver', + 'pkgrel', 'epoch', 'pkgdesc', 'url', 'filename', 'compressed_size', + 'installed_size', 'build_date', 'last_update', 'flag_date' ] + + def default(self, obj): + if hasattr(obj, '__iter__'): + # mainly for queryset serialization + return list(obj) + if isinstance(obj, Package): + data = dict((attr, getattr(obj, attr)) + for attr in self.pkg_attributes) + data['groups'] = obj.groups.all() + return data + if isinstance(obj, PackageFile): + filename = obj.filename or '' + return obj.directory + filename + if isinstance(obj, (Repo, Arch, PackageGroup)): + return obj.name.lower() + return super(PackageJSONEncoder, self).default(obj) + def opensearch(request): if request.is_secure(): domain = "https://%s" % request.META['HTTP_HOST'] @@ -146,15 +168,6 @@ def group_details(request, arch, name): } return direct_to_template(request, 'packages/packages_list.html', context) -def getmaintainer(request, name, repo, arch): - "Returns the maintainers as plaintext." - - pkg = get_object_or_404(Package, - pkgname=name, repo__name__iexact=repo, arch__name=arch) - names = [m.username for m in pkg.maintainers] - - return HttpResponse(str('\n'.join(names)), mimetype='text/plain') - def coerce_limit_value(value): if not value: return None @@ -287,6 +300,27 @@ def files(request, name, repo, arch): return direct_to_template(request, template, {'pkg':pkg, 'files':fileslist}) +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) + 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) + fileslist = PackageFile.objects.filter(pkg=pkg).order_by('directory', 'filename') + data = { + 'pkgname': pkg.pkgname, + 'repo': pkg.repo.name.lower(), + 'arch': pkg.arch.name.lower(), + 'files': fileslist, + } + to_json = simplejson.dumps(data, ensure_ascii=False, + cls=PackageJSONEncoder) + return HttpResponse(to_json, mimetype='application/json') + @permission_required('main.change_package') def unflag(request, name, repo, arch): pkg = get_object_or_404(Package, -- cgit v1.2.3-54-g00ecf From 4a9b6867a3a2786435316ab7deefa54257bb931d Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 15 Jun 2011 15:50:14 -0500 Subject: Refactor common select_related into manager method For a Package object query, we almost always did .select_related('arch', 'repo). Refactor this into the manager as a 'normal()' method so we can avoid sprinkling the same logic everywhere. Signed-off-by: Dan McGee --- devel/views.py | 4 ++-- feeds.py | 2 +- main/models.py | 11 ++++++----- packages/utils.py | 2 +- packages/views.py | 15 +++++++-------- public/utils.py | 6 +++--- sitemaps.py | 3 +-- 7 files changed, 21 insertions(+), 22 deletions(-) (limited to 'packages') diff --git a/devel/views.py b/devel/views.py index 2b8bd43e..1827f2ac 100644 --- a/devel/views.py +++ b/devel/views.py @@ -32,7 +32,7 @@ def index(request): '''the developer dashboard''' inner_q = PackageRelation.objects.filter(user=request.user).values('pkgbase') - flagged = Package.objects.select_related('arch', 'repo').filter( + flagged = Package.objects.normal().filter( flag_date__isnull=False, pkgbase__in=inner_q).order_by('pkgname') todopkgs = TodolistPkg.objects.select_related( @@ -135,7 +135,7 @@ def change_profile(request): @login_required def report(request, report, username=None): title = 'Developer Report' - packages = Package.objects.select_related('arch', 'repo') + packages = Package.objects.normal() names = attrs = user = None if report == 'old': diff --git a/feeds.py b/feeds.py index 269d0a38..74ae9ff9 100644 --- a/feeds.py +++ b/feeds.py @@ -51,7 +51,7 @@ def __call__(self, request, *args, **kwargs): def get_object(self, request, arch='', repo=''): obj = dict() - qs = Package.objects.select_related('arch', 'repo').order_by( + qs = Package.objects.normal().order_by( '-last_update') if arch != '': diff --git a/main/models.py b/main/models.py index eae55c8b..677647ac 100644 --- a/main/models.py +++ b/main/models.py @@ -74,8 +74,10 @@ def incomplete(self): class PackageManager(models.Manager): def flagged(self): - return self.get_query_set().filter(flag_date__isnull=False) + return self.filter(flag_date__isnull=False) + def normal(self): + return self.select_related('arch', 'repo') class Donor(models.Model): name = models.CharField(max_length=255, unique=True) @@ -255,8 +257,7 @@ def get_depends(self): deps = [] # TODO: we can use list comprehension and an 'in' query to make this more effective for dep in self.packagedepend_set.order_by('optional', 'depname'): - pkgs = Package.objects.select_related('arch', 'repo').filter( - pkgname=dep.depname) + pkgs = Package.objects.normal().filter(pkgname=dep.depname) if not self.arch.agnostic: # make sure we match architectures if possible pkgs = pkgs.filter(arch__in=self.applicable_arches()) @@ -320,7 +321,7 @@ def in_testing(self): if self.repo.testing: return None try: - return Package.objects.get(repo__testing=True, + return Package.objects.normal().get(repo__testing=True, pkgname=self.pkgname, arch=self.arch) except Package.DoesNotExist: return None @@ -328,7 +329,7 @@ def in_testing(self): def elsewhere(self): '''attempt to locate this package anywhere else, regardless of architecture or repository. Excludes this package from the list.''' - return Package.objects.select_related('arch', 'repo').filter( + return Package.objects.normal().filter( pkgname=self.pkgname).exclude(id=self.id).order_by( 'arch__name', 'repo__name') diff --git a/packages/utils.py b/packages/utils.py index 29a3087f..af4675bb 100644 --- a/packages/utils.py +++ b/packages/utils.py @@ -108,7 +108,7 @@ def get_differences_info(arch_a, arch_b): # column A will always have a value, column B might be NULL to_fetch.append(row[0]) # fetch all of the necessary packages - pkgs = Package.objects.select_related('arch', 'repo').in_bulk(to_fetch) + pkgs = Package.objects.normal().in_bulk(to_fetch) # now build a list of tuples containing differences differences = [] for row in results: diff --git a/packages/views.py b/packages/views.py index 44a1db96..5f559d6a 100644 --- a/packages/views.py +++ b/packages/views.py @@ -117,9 +117,8 @@ def details(request, name='', repo='', arch=''): arches = [ arch ] arches.extend(Arch.objects.filter(agnostic=True)) repo = get_object_or_404(Repo, name__iexact=repo) - pkgs = Package.objects.filter(pkgbase=name, - repo__testing=repo.testing, arch__in=arches) - pkgs = pkgs.select_related('arch', 'repo').order_by('pkgname') + pkgs = Package.objects.normal().filter(pkgbase=name, + repo__testing=repo.testing, arch__in=arches).order_by('pkgname') if len(pkgs) == 0: raise Http404 context = { @@ -156,8 +155,8 @@ 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.filter(groups__name=name, arch__in=arches) - pkgs = pkgs.select_related('arch', 'repo').order_by('pkgname') + pkgs = Package.objects.normal().filter( + groups__name=name, arch__in=arches).order_by('pkgname') if len(pkgs) == 0: raise Http404 context = { @@ -217,7 +216,7 @@ def __init__(self, *args, **kwargs): def search(request, page=None): limit = 50 - packages = Package.objects.select_related('arch', 'repo') + packages = Package.objects.normal() if request.GET: form = PackageSearchForm(data=request.GET) @@ -405,7 +404,7 @@ def flag(request, name, repo, arch): # already flagged. do nothing. return direct_to_template(request, 'packages/flagged.html', {'pkg': pkg}) # find all packages from (hopefully) the same PKGBUILD - pkgs = Package.objects.select_related('arch', 'repo').filter( + pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date__isnull=True, repo__testing=pkg.repo.testing).order_by( 'pkgname', 'repo__name', 'arch__name') @@ -460,7 +459,7 @@ def flag(request, name, repo, arch): def flag_confirmed(request, name, repo, arch): pkg = get_object_or_404(Package, pkgname=name, repo__name__iexact=repo, arch__name=arch) - pkgs = Package.objects.select_related('arch', 'repo').filter( + pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date=pkg.flag_date, repo__testing=pkg.repo.testing).order_by( 'pkgname', 'repo__name', 'arch__name') diff --git a/public/utils.py b/public/utils.py index fd29a845..0be3ebaa 100644 --- a/public/utils.py +++ b/public/utils.py @@ -1,6 +1,6 @@ from operator import attrgetter -from main.models import Arch, Package +from main.models import Arch, Package, Repo from main.utils import cache_function class RecentUpdate(object): @@ -57,8 +57,8 @@ def get_recent_updates(number=15): # grab a few extra so we can hopefully catch everything we need fetch = number * 6 for arch in Arch.objects.all(): - pkgs += list(Package.objects.select_related( - 'arch', 'repo').filter(arch=arch).order_by('-last_update')[:fetch]) + pkgs += list(Package.objects.normal().filter( + arch=arch).order_by('-last_update')[:fetch]) pkgs.sort(key=attrgetter('last_update')) updates = [] diff --git a/sitemaps.py b/sitemaps.py index e321fe85..1a3669ad 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -8,8 +8,7 @@ class PackagesSitemap(Sitemap): priority = "0.5" def items(self): - return Package.objects.select_related('arch', 'repo').all() - return Package.objects.all() + return Package.objects.normal() def lastmod(self, obj): return obj.last_update -- cgit v1.2.3-54-g00ecf