annotate downloads/views.py @ 887:9a15f7c27526

Actually save model object upon change. This commit was tested on the comments model. Additional logging added. Added check for Markdown image references. Added TODOs after observing behavior on comments.
author Brian Neal <bgneal@gmail.com>
date Tue, 03 Feb 2015 21:09:44 -0600
parents 41d0389fc85a
children a5ebc74dc3f3
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@845 148 if not download.is_public:
bgneal@845 149 raise Http404
bgneal@23 150 return render_to_response('downloads/download_detail.html', {
gremmie@1 151 'download' : download,
bgneal@404 152 },
gremmie@1 153 context_instance = RequestContext(request))
gremmie@1 154
gremmie@1 155 #######################################################################
gremmie@1 156
gremmie@1 157 @login_required
gremmie@1 158 def add(request):
gremmie@1 159 if request.method == 'POST':
gremmie@1 160 form = AddDownloadForm(request.POST, request.FILES)
gremmie@1 161 if form.is_valid():
gremmie@1 162 dl = form.save(commit=False)
gremmie@1 163 dl.user = request.user
gremmie@1 164 dl.ip_address = request.META.get('REMOTE_ADDR', None)
gremmie@1 165 dl.save()
gremmie@1 166 email_admins('New download for approval', """Hello,
gremmie@1 167
gremmie@1 168 A user has uploaded a new download for your approval.
gremmie@1 169 """)
gremmie@1 170 return HttpResponseRedirect(reverse('downloads-add_thanks'))
gremmie@1 171 else:
gremmie@1 172 form = AddDownloadForm()
gremmie@1 173
gremmie@1 174 return render_to_response('downloads/add.html', {
gremmie@1 175 'add_form': form,
gremmie@1 176 },
gremmie@1 177 context_instance=RequestContext(request))
gremmie@1 178
gremmie@1 179 #######################################################################
gremmie@1 180
gremmie@1 181 @login_required
gremmie@1 182 def thanks(request):
gremmie@1 183 return render_to_response('downloads/thanks.html', {
gremmie@1 184 },
gremmie@1 185 context_instance=RequestContext(request))
gremmie@1 186
gremmie@1 187 #######################################################################
gremmie@1 188
gremmie@1 189 @require_POST
gremmie@1 190 def rate_download(request):
gremmie@1 191 """This function is called by AJAX to rate a download."""
gremmie@1 192 if request.user.is_authenticated():
gremmie@1 193 id = request.POST.get('id', None)
gremmie@1 194 rating = request.POST.get('rating', None)
gremmie@1 195 if id is None or rating is None:
gremmie@1 196 return HttpResponseBadRequest('Missing id or rating.')
bgneal@404 197
gremmie@1 198 try:
gremmie@1 199 rating = int(rating)
gremmie@1 200 except ValueError:
gremmie@1 201 return HttpResponseBadRequest('Invalid rating.')
gremmie@1 202
gremmie@1 203 # rating will be from 0-4
gremmie@1 204 rating = min(5, max(1, rating))
gremmie@1 205
bgneal@480 206 download = get_object_or_404(Download.public_objects, pk=id)
gremmie@1 207
gremmie@1 208 # prevent multiple votes from the same user
bgneal@241 209 vote_record, created = VoteRecord.objects.get_or_create(
bgneal@241 210 download=download, user=request.user)
gremmie@1 211 if created:
gremmie@1 212 new_score = download.vote(rating)
gremmie@1 213 download.save()
gremmie@1 214 return HttpResponse(str(new_score))
gremmie@1 215 else:
gremmie@1 216 return HttpResponse('-1')
gremmie@1 217
gremmie@1 218 return HttpResponseForbidden('You must be logged in to rate a download.')
bgneal@404 219
bgneal@404 220 #######################################################################
bgneal@404 221
bgneal@404 222 @require_POST
bgneal@404 223 def request_download(request):
bgneal@404 224 """
bgneal@404 225 This function is called by AJAX to request a download. We update the hit
bgneal@404 226 count and then return a JSON object of the form:
bgneal@404 227 { id: download-id, 'url': link-to-download }
bgneal@404 228
bgneal@404 229 """
bgneal@404 230 if request.user.is_authenticated():
bgneal@404 231 dl_id = request.POST.get('id')
bgneal@404 232 if dl_id:
bgneal@404 233 try:
bgneal@404 234 dl = Download.public_objects.get(pk=dl_id)
bgneal@404 235 except Download.DoesNotExist:
bgneal@404 236 return HttpResponseNotFound("Download not found")
bgneal@404 237
bgneal@404 238 dl.hits += 1
bgneal@404 239 dl.save()
bgneal@404 240
bgneal@404 241 s = json.dumps({'id': dl_id, 'url': dl.file.url})
bgneal@404 242 return HttpResponse(s, content_type='application/json')
bgneal@404 243
bgneal@404 244 return HttpResponseForbidden('An error occurred.')