from datetime import datetime from django import forms from django.contrib.admin.widgets import AdminDateWidget 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.utils import simplejson from main.models import Package, Arch, Repo from main.utils import make_choice from ..models import PackageRelation from ..utils import PackageJSONEncoder def coerce_limit_value(value): if not value: return None if value == 'all': # negative value indicates show all results return -1 value = int(value) if value < 0: raise ValueError return value class LimitTypedChoiceField(forms.TypedChoiceField): def valid_value(self, value): try: coerce_limit_value(value) return True except (ValueError, TypeError): return False class PackageSearchForm(forms.Form): repo = forms.MultipleChoiceField(required=False) arch = forms.MultipleChoiceField(required=False) name = forms.CharField(required=False) desc = forms.CharField(required=False) q = forms.CharField(required=False) sort = forms.CharField(required=False) maintainer = forms.ChoiceField(required=False) packager = forms.ChoiceField(required=False) last_update = forms.DateField(required=False, widget=AdminDateWidget(), label='Last Updated After') flagged = forms.ChoiceField( choices=[('', 'All')] + make_choice(['Flagged', 'Not Flagged']), required=False) limit = LimitTypedChoiceField( choices=make_choice([50, 100, 250]) + [('all', 'All')], coerce=coerce_limit_value, required=False, initial=50) def __init__(self, *args, **kwargs): super(PackageSearchForm, self).__init__(*args, **kwargs) self.fields['repo'].choices = make_choice( [repo.name for repo in Repo.objects.all()]) self.fields['arch'].choices = make_choice( [arch.name for arch in Arch.objects.all()]) self.fields['q'].widget.attrs.update({"size": "30"}) maints = User.objects.filter(is_active=True).order_by( 'first_name', 'last_name') self.fields['maintainer'].choices = \ [('', 'All'), ('orphan', 'Orphan')] + \ [(m.username, m.get_full_name()) for m in maints] self.fields['packager'].choices = \ [('', '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( repo__name__in=form.cleaned_data['repo']) if form.cleaned_data['arch']: packages = packages.filter( arch__name__in=form.cleaned_data['arch']) if form.cleaned_data['maintainer'] == 'orphan': inner_q = PackageRelation.objects.all().values('pkgbase') packages = packages.exclude(pkgbase__in=inner_q) elif form.cleaned_data['maintainer']: inner_q = PackageRelation.objects.filter( user__username=form.cleaned_data['maintainer']).values('pkgbase') packages = packages.filter(pkgbase__in=inner_q) if form.cleaned_data['packager'] == 'unknown': packages = packages.filter(packager__isnull=True) elif form.cleaned_data['packager']: packages = packages.filter( packager__username=form.cleaned_data['packager']) if form.cleaned_data['flagged'] == 'Flagged': packages = packages.filter(flag_date__isnull=False) elif form.cleaned_data['flagged'] == 'Not Flagged': packages = packages.filter(flag_date__isnull=True) if form.cleaned_data['last_update']: lu = form.cleaned_data['last_update'] packages = packages.filter(last_update__gte= datetime(lu.year, lu.month, lu.day, 0, 0)) if form.cleaned_data['name']: name = form.cleaned_data['name'] packages = packages.filter(pkgname=name) if form.cleaned_data['desc']: desc = form.cleaned_data['desc'] packages = packages.filter(pkgdesc__icontains=desc) if form.cleaned_data['q']: query = form.cleaned_data['q'] q = Q(pkgname__icontains=query) | Q(pkgdesc__icontains=query) packages = packages.filter(q) 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'] 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) def search_json(request): limit = 250 container = { 'version': 2, 'limit': limit, 'valid': False, 'results': [], } if request.GET: form = PackageSearchForm(data=request.GET) if form.is_valid(): packages = Package.objects.normal() packages = parse_form(form, packages)[:limit] container['results'] = packages container['valid'] = True to_json = simplejson.dumps(container, ensure_ascii=False, cls=PackageJSONEncoder) return HttpResponse(to_json, mimetype='application/json') # vim: set ts=4 sw=4 et: