annotate downloads/views.py @ 697:67f8d49a9377

Cleaned up the code a bit. Separated the S3 stuff out into its own class. This class maybe should be in core. Still want to do some kind of context manager around the temporary file we are creating to ensure it gets deleted.
author Brian Neal <bgneal@gmail.com>
date Sun, 08 Sep 2013 21:02:58 -0500
parents 89b240fe9297
children 41d0389fc85a
rev   line source
gremmie@1 1 """
gremmie@1 2 Views for the downloads application.
gremmie@1 3 """
bgneal@679 4 import json
gremmie@1 5
bgneal@480 6 from django.shortcuts import render_to_response, get_object_or_404
gremmie@1 7 from django.template import RequestContext
gremmie@1 8 from django.contrib.auth.decorators import login_required
gremmie@1 9 from django.http import Http404
gremmie@1 10 from django.http import HttpResponse
gremmie@1 11 from django.http import HttpResponseRedirect
gremmie@1 12 from django.http import HttpResponseForbidden
gremmie@1 13 from django.http import HttpResponseBadRequest
bgneal@404 14 from django.http import HttpResponseNotFound
bgneal@92 15 from django.core.paginator import InvalidPage
gremmie@1 16 from django.core.urlresolvers import reverse
gremmie@1 17 from django.views.decorators.http import require_POST
gremmie@1 18
gremmie@1 19 from core.paginator import DiggPaginator
gremmie@1 20 from core.functions import email_admins
bgneal@241 21 from core.functions import get_page
gremmie@1 22 from downloads.models import Category
gremmie@1 23 from downloads.models import Download
gremmie@1 24 from downloads.models import VoteRecord
gremmie@1 25 from downloads.forms import AddDownloadForm
gremmie@1 26
gremmie@1 27 #######################################################################
gremmie@1 28
bgneal@242 29 DLS_PER_PAGE = 10
gremmie@1 30
gremmie@1 31 def create_paginator(dls):
gremmie@1 32 return DiggPaginator(dls, DLS_PER_PAGE, body=5, tail=3, margin=3, padding=2)
gremmie@1 33
gremmie@1 34 #######################################################################
gremmie@1 35
gremmie@1 36 @login_required
gremmie@1 37 def index(request):
gremmie@1 38 categories = Category.objects.all()
gremmie@1 39 total_dls = Download.public_objects.all().count()
gremmie@1 40 return render_to_response('downloads/index.html', {
gremmie@1 41 'categories': categories,
gremmie@1 42 'total_dls': total_dls,
gremmie@1 43 },
gremmie@1 44 context_instance = RequestContext(request))
gremmie@1 45
gremmie@1 46 #######################################################################
gremmie@1 47 # Maps URL component to database field name for the Download table:
gremmie@1 48
gremmie@1 49 DOWNLOAD_FIELD_MAP = {
bgneal@404 50 'title': 'title',
gremmie@1 51 'date': '-date_added',
gremmie@1 52 'rating': '-average_score',
gremmie@1 53 'hits': '-hits'
gremmie@1 54 }
gremmie@1 55
gremmie@1 56 @login_required
bgneal@241 57 def category(request, slug, sort='title'):
bgneal@480 58
bgneal@480 59 cat = get_object_or_404(Category, slug=slug)
gremmie@1 60
gremmie@1 61 if sort not in DOWNLOAD_FIELD_MAP:
gremmie@1 62 sort = 'title'
gremmie@1 63 order_by = DOWNLOAD_FIELD_MAP[sort]
gremmie@1 64
bgneal@190 65 downloads = Download.public_objects.filter(category=cat.pk).order_by(
bgneal@190 66 order_by)
gremmie@1 67 paginator = create_paginator(downloads)
bgneal@241 68 page = get_page(request.GET)
gremmie@1 69 try:
bgneal@241 70 the_page = paginator.page(page)
gremmie@1 71 except InvalidPage:
gremmie@1 72 raise Http404
gremmie@1 73
gremmie@1 74 return render_to_response('downloads/download_list.html', {
gremmie@1 75 's' : sort,
gremmie@1 76 'category' : cat,
bgneal@404 77 'page' : the_page,
bgneal@404 78 },
gremmie@1 79 context_instance = RequestContext(request))
gremmie@1 80
gremmie@1 81 #######################################################################
gremmie@1 82
gremmie@1 83 @login_required
gremmie@1 84 def new(request):
bgneal@243 85 """Display new downloads with pagination."""
bgneal@243 86
bgneal@243 87 downloads = Download.public_objects.order_by('-date_added')
bgneal@243 88
bgneal@243 89 paginator = create_paginator(downloads)
bgneal@243 90 page = get_page(request.GET)
bgneal@243 91 try:
bgneal@243 92 the_page = paginator.page(page)
bgneal@243 93 except InvalidPage:
bgneal@243 94 raise Http404
bgneal@243 95
gremmie@1 96 return render_to_response('downloads/download_summary.html', {
bgneal@243 97 'page': the_page,
bgneal@243 98 'title': 'Newest Downloads',
bgneal@404 99 },
gremmie@1 100 context_instance = RequestContext(request))
gremmie@1 101
gremmie@1 102 #######################################################################
gremmie@1 103
gremmie@1 104 @login_required
gremmie@1 105 def popular(request):
bgneal@243 106 """Display popular downloads with pagination."""
bgneal@243 107
bgneal@243 108 downloads = Download.public_objects.order_by('-hits')
bgneal@243 109
bgneal@243 110 paginator = create_paginator(downloads)
bgneal@243 111 page = get_page(request.GET)
bgneal@243 112 try:
bgneal@243 113 the_page = paginator.page(page)
bgneal@243 114 except InvalidPage:
bgneal@243 115 raise Http404
bgneal@243 116
gremmie@1 117 return render_to_response('downloads/download_summary.html', {
bgneal@243 118 'page': the_page,
bgneal@243 119 'title': 'Popular Downloads',
bgneal@404 120 },
gremmie@1 121 context_instance = RequestContext(request))
gremmie@1 122
gremmie@1 123 #######################################################################
gremmie@1 124
gremmie@1 125 @login_required
gremmie@1 126 def rating(request):
bgneal@243 127 """Display downloads by rating with pagination."""
bgneal@243 128
bgneal@243 129 downloads = Download.public_objects.order_by('-average_score')
bgneal@243 130 paginator = create_paginator(downloads)
bgneal@243 131 page = get_page(request.GET)
bgneal@243 132 try:
bgneal@243 133 the_page = paginator.page(page)
bgneal@243 134 except InvalidPage:
bgneal@243 135 raise Http404
bgneal@243 136
gremmie@1 137 return render_to_response('downloads/download_summary.html', {
bgneal@243 138 'page': the_page,
bgneal@243 139 'title': 'Highest Rated Downloads',
bgneal@404 140 },
gremmie@1 141 context_instance = RequestContext(request))
gremmie@1 142
gremmie@1 143 #######################################################################
gremmie@1 144
gremmie@1 145 @login_required
bgneal@23 146 def details(request, id):
bgneal@480 147 download = get_object_or_404(Download.public_objects, pk=id)
bgneal@23 148 return render_to_response('downloads/download_detail.html', {
gremmie@1 149 'download' : download,
bgneal@404 150 },
gremmie@1 151 context_instance = RequestContext(request))
gremmie@1 152
gremmie@1 153 #######################################################################
gremmie@1 154
gremmie@1 155 @login_required
gremmie@1 156 def add(request):
gremmie@1 157 if request.method == 'POST':
gremmie@1 158 form = AddDownloadForm(request.POST, request.FILES)
gremmie@1 159 if form.is_valid():
gremmie@1 160 dl = form.save(commit=False)
gremmie@1 161 dl.user = request.user
gremmie@1 162 dl.ip_address = request.META.get('REMOTE_ADDR', None)
gremmie@1 163 dl.save()
gremmie@1 164 email_admins('New download for approval', """Hello,
gremmie@1 165
gremmie@1 166 A user has uploaded a new download for your approval.
gremmie@1 167 """)
gremmie@1 168 return HttpResponseRedirect(reverse('downloads-add_thanks'))
gremmie@1 169 else:
gremmie@1 170 form = AddDownloadForm()
gremmie@1 171
gremmie@1 172 return render_to_response('downloads/add.html', {
gremmie@1 173 'add_form': form,
gremmie@1 174 },
gremmie@1 175 context_instance=RequestContext(request))
gremmie@1 176
gremmie@1 177 #######################################################################
gremmie@1 178
gremmie@1 179 @login_required
gremmie@1 180 def thanks(request):
gremmie@1 181 return render_to_response('downloads/thanks.html', {
gremmie@1 182 },
gremmie@1 183 context_instance=RequestContext(request))
gremmie@1 184
gremmie@1 185 #######################################################################
gremmie@1 186
gremmie@1 187 @require_POST
gremmie@1 188 def rate_download(request):
gremmie@1 189 """This function is called by AJAX to rate a download."""
gremmie@1 190 if request.user.is_authenticated():
gremmie@1 191 id = request.POST.get('id', None)
gremmie@1 192 rating = request.POST.get('rating', None)
gremmie@1 193 if id is None or rating is None:
gremmie@1 194 return HttpResponseBadRequest('Missing id or rating.')
bgneal@404 195
gremmie@1 196 try:
gremmie@1 197 rating = int(rating)
gremmie@1 198 except ValueError:
gremmie@1 199 return HttpResponseBadRequest('Invalid rating.')
gremmie@1 200
gremmie@1 201 # rating will be from 0-4
gremmie@1 202 rating = min(5, max(1, rating))
gremmie@1 203
bgneal@480 204 download = get_object_or_404(Download.public_objects, pk=id)
gremmie@1 205
gremmie@1 206 # prevent multiple votes from the same user
bgneal@241 207 vote_record, created = VoteRecord.objects.get_or_create(
bgneal@241 208 download=download, user=request.user)
gremmie@1 209 if created:
gremmie@1 210 new_score = download.vote(rating)
gremmie@1 211 download.save()
gremmie@1 212 return HttpResponse(str(new_score))
gremmie@1 213 else:
gremmie@1 214 return HttpResponse('-1')
gremmie@1 215
gremmie@1 216 return HttpResponseForbidden('You must be logged in to rate a download.')
bgneal@404 217
bgneal@404 218 #######################################################################
bgneal@404 219
bgneal@404 220 @require_POST
bgneal@404 221 def request_download(request):
bgneal@404 222 """
bgneal@404 223 This function is called by AJAX to request a download. We update the hit
bgneal@404 224 count and then return a JSON object of the form:
bgneal@404 225 { id: download-id, 'url': link-to-download }
bgneal@404 226
bgneal@404 227 """
bgneal@404 228 if request.user.is_authenticated():
bgneal@404 229 dl_id = request.POST.get('id')
bgneal@404 230 if dl_id:
bgneal@404 231 try:
bgneal@404 232 dl = Download.public_objects.get(pk=dl_id)
bgneal@404 233 except Download.DoesNotExist:
bgneal@404 234 return HttpResponseNotFound("Download not found")
bgneal@404 235
bgneal@404 236 dl.hits += 1
bgneal@404 237 dl.save()
bgneal@404 238
bgneal@404 239 s = json.dumps({'id': dl_id, 'url': dl.file.url})
bgneal@404 240 return HttpResponse(s, content_type='application/json')
bgneal@404 241
bgneal@404 242 return HttpResponseForbidden('An error occurred.')