simplify some @repeat_on_conflict decorated methods
[mygpo.git] / mygpo / directory / views.py
blob4c136a64a74d453f2c5fcd4ca5db4cc1af41ce2d
1 from itertools import imap as map
2 from math import ceil
4 from django.http import HttpResponseNotFound, Http404, HttpResponseRedirect
5 from django.core.urlresolvers import reverse
6 from django.shortcuts import render
7 from django.contrib.sites.models import RequestSite
8 from django.views.decorators.cache import cache_control
9 from django.views.decorators.vary import vary_on_cookie
10 from django.utils.decorators import method_decorator
11 from django.views.generic.base import View
12 from django.contrib.auth.decorators import login_required
13 from django.contrib import messages
14 from django.utils.translation import ugettext as _
16 from feedservice.parse.models import ParserException
17 from feedservice.parse import FetchFeedException
19 from mygpo.core.proxy import proxy_object
20 from mygpo.directory.toplist import PodcastToplist, EpisodeToplist, \
21 TrendingPodcasts
22 from mygpo.directory.search import search_podcasts
23 from mygpo.web.utils import process_lang_params, get_language_names, \
24 get_page_list, get_podcast_link_target
25 from mygpo.directory.tags import Topics
26 from mygpo.users.models import User
27 from mygpo.data.feeddownloader import PodcastUpdater, NoEpisodesException
28 from mygpo.db.couchdb.podcast import get_podcast_languages, podcasts_by_id, \
29 random_podcasts, podcasts_to_dict, podcast_for_url
30 from mygpo.db.couchdb.directory import category_for_tag
31 from mygpo.db.couchdb.podcastlist import random_podcastlists, \
32 podcastlist_count, podcastlists_by_rating
35 @vary_on_cookie
36 @cache_control(private=True)
37 def toplist(request, num=100, lang=None):
39 lang = process_lang_params(request)
41 toplist = PodcastToplist(lang)
42 entries = toplist[:num]
44 max_subscribers = max([p.subscriber_count() for (oldp, p) in entries]) if entries else 0
45 current_site = RequestSite(request)
47 languages = get_podcast_languages()
48 all_langs = get_language_names(languages)
50 return render(request, 'toplist.html', {
51 'entries': entries,
52 'max_subscribers': max_subscribers,
53 'url': current_site,
54 'language': lang,
55 'all_languages': all_langs,
59 class Carousel(View):
60 """ A carousel demo """
62 @method_decorator(cache_control(private=True))
63 @method_decorator(vary_on_cookie)
64 def get(self, request):
66 return render(request, 'carousel.html', {
67 # evaluated lazyly, cached by template
68 'topics': Topics(),
72 class Directory(View):
73 """ The main directory page """
75 @method_decorator(cache_control(private=True))
76 @method_decorator(vary_on_cookie)
77 def get(self, request):
79 return render(request, 'directory.html', {
81 # evaluated lazyly, cached by template
82 'topics': Topics(),
83 'trending_podcasts': TrendingPodcasts(''),
84 'podcastlists': self.get_random_list(),
85 'random_podcasts': self.get_random_podcast(),
89 def get_random_list(self, podcasts_per_list=5):
90 random_list = next(random_podcastlists(), None)
91 list_owner = None
92 if random_list:
93 random_list = proxy_object(random_list)
94 random_list.more_podcasts = max(0, len(random_list.podcasts) - podcasts_per_list)
95 random_list.podcasts = podcasts_by_id(random_list.podcasts[:podcasts_per_list])
96 random_list.user = User.get(random_list.user)
98 yield random_list
100 def get_random_podcast(self):
101 random_podcast = next(random_podcasts(), None)
102 if random_podcast:
103 yield random_podcast.get_podcast()
106 @cache_control(private=True)
107 @vary_on_cookie
108 def category(request, category, page_size=20):
109 category = category_for_tag(category)
110 if not category:
111 return HttpResponseNotFound()
113 # Make sure page request is an int. If not, deliver first page.
114 try:
115 page = int(request.GET.get('page', '1'))
116 except ValueError:
117 page = 1
119 entries = category.get_podcasts( (page-1) * page_size, page*page_size )
120 podcasts = filter(None, entries)
121 num_pages = len(category.podcasts) / page_size
123 page_list = get_page_list(1, num_pages, page, 15)
125 return render(request, 'category.html', {
126 'entries': podcasts,
127 'category': category.label,
128 'page_list': page_list,
133 RESULTS_PER_PAGE=20
135 @cache_control(private=True)
136 @vary_on_cookie
137 def search(request, template='search.html', args={}):
139 if 'q' in request.GET:
140 q = request.GET.get('q', '').encode('utf-8')
142 try:
143 page = int(request.GET.get('page', 1))
144 except ValueError:
145 page = 1
147 results, total = search_podcasts(q=q, skip=RESULTS_PER_PAGE*(page-1))
148 num_pages = total / RESULTS_PER_PAGE
150 page_list = get_page_list(1, num_pages, page, 15)
152 else:
153 results = []
154 q = None
155 page_list = []
157 max_subscribers = max([p.subscriber_count() for p in results] + [0])
158 current_site = RequestSite(request)
160 return render(request, template, dict(
161 q= q,
162 results= results,
163 page_list= page_list,
164 max_subscribers= max_subscribers,
165 domain= current_site.domain,
166 **args
170 @cache_control(private=True)
171 @vary_on_cookie
172 def episode_toplist(request, num=100):
173 lang = process_lang_params(request)
175 toplist = EpisodeToplist(language=lang)
176 entries = list(map(proxy_object, toplist[:num]))
178 # load podcast objects
179 podcast_ids = [e.podcast for e in entries]
180 podcasts = podcasts_to_dict(podcast_ids, True)
181 for entry in entries:
182 entry.podcast = podcasts.get(entry.podcast, None)
184 current_site = RequestSite(request)
186 # Determine maximum listener amount (or 0 if no entries exist)
187 max_listeners = max([0]+[e.listeners for e in entries])
189 languages = get_podcast_languages()
190 all_langs = get_language_names(languages)
192 return render(request, 'episode_toplist.html', {
193 'entries': entries,
194 'max_listeners': max_listeners,
195 'url': current_site,
196 'language': lang,
197 'all_languages': all_langs,
201 @cache_control(private=True)
202 @vary_on_cookie
203 def podcast_lists(request, page_size=20):
205 # Make sure page request is an int. If not, deliver first page.
206 try:
207 page = int(request.GET.get('page', '1'))
208 except ValueError:
209 page = 1
211 lists = podcastlists_by_rating(skip=(page-1) * page_size, limit=page_size)
214 def _prepare_list(l):
215 user = User.get(l.user)
216 l = proxy_object(l)
217 l.username = user.username
218 return l
220 lists = map(_prepare_list, lists)
222 num_pages = int(ceil(podcastlist_count() / float(page_size)))
224 page_list = get_page_list(1, num_pages, page, 15)
226 return render(request, 'podcast_lists.html', {
227 'lists': lists,
228 'page_list': page_list,
233 class MissingPodcast(View):
234 """ Check if a podcast is missing """
236 @method_decorator(login_required)
237 def get(self, request):
239 site = RequestSite(request)
241 # check if we're doing a query
242 url = request.GET.get('q', None)
244 if not url:
245 podcast = None
246 can_add = False
248 else:
249 podcast = podcast_for_url(url)
251 # if the podcast does already exist, there's nothing more to do
252 if podcast:
253 can_add = False
255 # check if we could add a podcast for the given URL
256 else:
257 podcast = False
258 updater = PodcastUpdater()
260 try:
261 can_add = updater.verify_podcast_url(url)
263 except (ParserException, FetchFeedException,
264 NoEpisodesException) as ex:
265 can_add = False
266 messages.error(request, str(ex))
268 return render(request, 'missing.html', {
269 'site': site,
270 'q': url,
271 'podcast': podcast,
272 'can_add': can_add,
276 class AddPodcast(View):
277 """ Add a missing podcast"""
279 @method_decorator(login_required)
280 @method_decorator(cache_control(private=True))
281 @method_decorator(vary_on_cookie)
282 def post(self, request):
284 url = request.POST.get('url', None)
286 if not url:
287 raise Http404
289 updater = PodcastUpdater()
291 try:
292 podcast = updater.update_podcast_url(url)
294 messages.success(request, _('The podcast has been added'))
296 return HttpResponseRedirect(get_podcast_link_target(podcast))
298 except (ParserException, FetchFeedException,
299 NoEpisodesException) as ex:
300 messages.error(request, str(ex))
302 add_page = '%s?q=%s' % (reverse('missing-podcast'), url)
303 return HttpResponseRedirect(add_page)