gremmie@1: """ gremmie@1: Views for the downloads application. gremmie@1: """ bgneal@679: import json gremmie@1: bgneal@1031: from django.shortcuts import render, get_object_or_404 gremmie@1: from django.contrib.auth.decorators import login_required gremmie@1: from django.http import Http404 gremmie@1: from django.http import HttpResponse gremmie@1: from django.http import HttpResponseRedirect gremmie@1: from django.http import HttpResponseForbidden gremmie@1: from django.http import HttpResponseBadRequest bgneal@404: from django.http import HttpResponseNotFound bgneal@92: from django.core.paginator import InvalidPage gremmie@1: from django.core.urlresolvers import reverse gremmie@1: from django.views.decorators.http import require_POST gremmie@1: gremmie@1: from core.paginator import DiggPaginator gremmie@1: from core.functions import email_admins bgneal@241: from core.functions import get_page gremmie@1: from downloads.models import Category gremmie@1: from downloads.models import Download gremmie@1: from downloads.models import VoteRecord gremmie@1: from downloads.forms import AddDownloadForm gremmie@1: gremmie@1: ####################################################################### gremmie@1: bgneal@242: DLS_PER_PAGE = 10 gremmie@1: gremmie@1: def create_paginator(dls): gremmie@1: return DiggPaginator(dls, DLS_PER_PAGE, body=5, tail=3, margin=3, padding=2) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def index(request): gremmie@1: categories = Category.objects.all() gremmie@1: total_dls = Download.public_objects.all().count() bgneal@1031: return render(request, 'downloads/index.html', { gremmie@1: 'categories': categories, gremmie@1: 'total_dls': total_dls, bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: # Maps URL component to database field name for the Download table: gremmie@1: gremmie@1: DOWNLOAD_FIELD_MAP = { bgneal@404: 'title': 'title', gremmie@1: 'date': '-date_added', gremmie@1: 'rating': '-average_score', gremmie@1: 'hits': '-hits' gremmie@1: } gremmie@1: gremmie@1: @login_required bgneal@241: def category(request, slug, sort='title'): bgneal@480: bgneal@480: cat = get_object_or_404(Category, slug=slug) gremmie@1: gremmie@1: if sort not in DOWNLOAD_FIELD_MAP: gremmie@1: sort = 'title' gremmie@1: order_by = DOWNLOAD_FIELD_MAP[sort] gremmie@1: bgneal@190: downloads = Download.public_objects.filter(category=cat.pk).order_by( bgneal@190: order_by) gremmie@1: paginator = create_paginator(downloads) bgneal@241: page = get_page(request.GET) gremmie@1: try: bgneal@241: the_page = paginator.page(page) gremmie@1: except InvalidPage: gremmie@1: raise Http404 gremmie@1: bgneal@1031: return render(request, 'downloads/download_list.html', { gremmie@1: 's' : sort, gremmie@1: 'category' : cat, bgneal@404: 'page' : the_page, bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def new(request): bgneal@243: """Display new downloads with pagination.""" bgneal@243: bgneal@243: downloads = Download.public_objects.order_by('-date_added') bgneal@243: bgneal@243: paginator = create_paginator(downloads) bgneal@243: page = get_page(request.GET) bgneal@243: try: bgneal@243: the_page = paginator.page(page) bgneal@243: except InvalidPage: bgneal@243: raise Http404 bgneal@243: bgneal@1031: return render(request, 'downloads/download_summary.html', { bgneal@243: 'page': the_page, bgneal@243: 'title': 'Newest Downloads', bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def popular(request): bgneal@243: """Display popular downloads with pagination.""" bgneal@243: bgneal@243: downloads = Download.public_objects.order_by('-hits') bgneal@243: bgneal@243: paginator = create_paginator(downloads) bgneal@243: page = get_page(request.GET) bgneal@243: try: bgneal@243: the_page = paginator.page(page) bgneal@243: except InvalidPage: bgneal@243: raise Http404 bgneal@243: bgneal@1031: return render(request, 'downloads/download_summary.html', { bgneal@243: 'page': the_page, bgneal@243: 'title': 'Popular Downloads', bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def rating(request): bgneal@243: """Display downloads by rating with pagination.""" bgneal@243: bgneal@243: downloads = Download.public_objects.order_by('-average_score') bgneal@243: paginator = create_paginator(downloads) bgneal@243: page = get_page(request.GET) bgneal@243: try: bgneal@243: the_page = paginator.page(page) bgneal@243: except InvalidPage: bgneal@243: raise Http404 bgneal@243: bgneal@1031: return render(request, 'downloads/download_summary.html', { bgneal@243: 'page': the_page, bgneal@243: 'title': 'Highest Rated Downloads', bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required bgneal@23: def details(request, id): bgneal@480: download = get_object_or_404(Download.public_objects, pk=id) bgneal@845: if not download.is_public: bgneal@845: raise Http404 bgneal@1031: return render(request, 'downloads/download_detail.html', { gremmie@1: 'download' : download, bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def add(request): gremmie@1: if request.method == 'POST': gremmie@1: form = AddDownloadForm(request.POST, request.FILES) gremmie@1: if form.is_valid(): gremmie@1: dl = form.save(commit=False) gremmie@1: dl.user = request.user gremmie@1: dl.ip_address = request.META.get('REMOTE_ADDR', None) bgneal@1023: dl.save(html=form.html) gremmie@1: email_admins('New download for approval', """Hello, gremmie@1: gremmie@1: A user has uploaded a new download for your approval. gremmie@1: """) gremmie@1: return HttpResponseRedirect(reverse('downloads-add_thanks')) gremmie@1: else: gremmie@1: form = AddDownloadForm() gremmie@1: bgneal@1031: return render(request, 'downloads/add.html', { gremmie@1: 'add_form': form, bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @login_required gremmie@1: def thanks(request): bgneal@1031: return render(request, 'downloads/thanks.html', { bgneal@1031: }) gremmie@1: gremmie@1: ####################################################################### gremmie@1: gremmie@1: @require_POST gremmie@1: def rate_download(request): gremmie@1: """This function is called by AJAX to rate a download.""" gremmie@1: if request.user.is_authenticated(): gremmie@1: id = request.POST.get('id', None) gremmie@1: rating = request.POST.get('rating', None) gremmie@1: if id is None or rating is None: gremmie@1: return HttpResponseBadRequest('Missing id or rating.') bgneal@404: gremmie@1: try: gremmie@1: rating = int(rating) gremmie@1: except ValueError: gremmie@1: return HttpResponseBadRequest('Invalid rating.') gremmie@1: gremmie@1: # rating will be from 0-4 gremmie@1: rating = min(5, max(1, rating)) gremmie@1: bgneal@480: download = get_object_or_404(Download.public_objects, pk=id) gremmie@1: gremmie@1: # prevent multiple votes from the same user bgneal@241: vote_record, created = VoteRecord.objects.get_or_create( bgneal@241: download=download, user=request.user) gremmie@1: if created: gremmie@1: new_score = download.vote(rating) gremmie@1: download.save() gremmie@1: return HttpResponse(str(new_score)) gremmie@1: else: gremmie@1: return HttpResponse('-1') gremmie@1: gremmie@1: return HttpResponseForbidden('You must be logged in to rate a download.') bgneal@404: bgneal@404: ####################################################################### bgneal@404: bgneal@404: @require_POST bgneal@404: def request_download(request): bgneal@404: """ bgneal@404: This function is called by AJAX to request a download. We update the hit bgneal@404: count and then return a JSON object of the form: bgneal@404: { id: download-id, 'url': link-to-download } bgneal@404: bgneal@404: """ bgneal@404: if request.user.is_authenticated(): bgneal@404: dl_id = request.POST.get('id') bgneal@404: if dl_id: bgneal@404: try: bgneal@404: dl = Download.public_objects.get(pk=dl_id) bgneal@404: except Download.DoesNotExist: bgneal@404: return HttpResponseNotFound("Download not found") bgneal@404: bgneal@404: dl.hits += 1 bgneal@404: dl.save() bgneal@404: bgneal@404: s = json.dumps({'id': dl_id, 'url': dl.file.url}) bgneal@404: return HttpResponse(s, content_type='application/json') bgneal@404: bgneal@404: return HttpResponseForbidden('An error occurred.')