unify book list fields in api
[wolnelektury.git] / src / wolnelektury / views.py
1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 from datetime import date, datetime
6 import feedparser
7 from allauth.socialaccount.views import SignupView
8
9 from django.conf import settings
10 from django.contrib import auth
11 from django.contrib.auth.decorators import login_required
12 from django.contrib.auth.forms import AuthenticationForm
13 from django.core.cache import cache
14 from django.http import HttpResponse, HttpResponseRedirect
15 from django.shortcuts import render
16 from django.utils.http import urlquote_plus
17 from django.utils.translation import ugettext_lazy as _
18 from django.views.decorators.cache import never_cache
19
20 from ajaxable.utils import AjaxableFormView
21 from ajaxable.utils import placeholdized
22 from catalogue.models import Book, Collection, Tag, Fragment
23 from ssify import ssi_included
24
25 from social.utils import get_or_choose_cite
26 from wolnelektury.forms import RegistrationForm, SocialSignupForm
27
28
29 def main_page(request):
30     ctx = {
31         'last_published': Book.objects.exclude(cover_thumb='').filter(parent=None).order_by('-created_at')[:6],
32         'theme_books': [],
33         'cite': get_or_choose_cite(request),
34     }
35
36     # for category in ('author', 'epoch', 'genre', 'kind'):
37     #     try:
38     #         ctx[category] = Tag.objects.filter(category=category).order_by('?')[:1][0]
39     #     except IndexError:
40     #         pass
41
42     # FIXME: find this theme and books properly.
43     if Fragment.objects.exists():
44         while True:
45             ctx['theme'] = Tag.objects.filter(category='theme').order_by('?')[:1][0]
46             tf = Fragment.tagged.with_any([ctx['theme']]).select_related('book').order_by('?')[:100]
47             if not tf:
48                 continue
49             ctx['theme_fragment'] = tf[0]
50             for f in tf:
51                 if f.book not in ctx['theme_books']:
52                     ctx['theme_books'].append(f.book)
53                 if len(ctx['theme_books']) == 3:
54                     break
55             break
56
57     # Choose a collection for main.
58     try:
59         ctx['collection'] = Collection.objects.order_by('?')[:1][0]
60     except IndexError:
61         pass
62
63     ctx['best'] = Book.objects.order_by('?')[:5]
64
65     return render(request, "main_page.html", ctx)
66
67
68 class LoginFormView(AjaxableFormView):
69     form_class = AuthenticationForm
70     template = "auth/login.html"
71     placeholdize = True
72     title = _('Sign in')
73     submit = _('Sign in')
74     ajax_redirect = True
75
76     def __call__(self, request):
77         if request.user.is_authenticated():
78             return self.redirect_or_refresh(
79                 request, '/',
80                 message=_('Already logged in as user %(user)s', ) % {'user': request.user.username})
81         return super(LoginFormView, self).__call__(request)
82
83     def success(self, form, request):
84         auth.login(request, form.get_user())
85
86
87 class RegisterFormView(AjaxableFormView):
88     form_class = RegistrationForm
89     template = "auth/register.html"
90     placeholdize = True
91     title = _('Register')
92     submit = _('Register')
93     ajax_redirect = True
94     form_prefix = 'register'
95     honeypot = True
96
97     def __call__(self, request):
98         if request.user.is_authenticated():
99             return self.redirect_or_refresh(
100                 request, '/',
101                 message=_('Already logged in as user %(user)s', ) % {'user': request.user.username})
102         return super(RegisterFormView, self).__call__(request)
103
104     def success(self, form, request):
105         form.save()
106         user = auth.authenticate(
107             username=form.cleaned_data['username'],
108             password=form.cleaned_data['password1']
109         )
110         auth.login(request, user)
111
112
113 class LoginRegisterFormView(LoginFormView):
114     template = 'auth/login_register.html'
115     title = _('You have to be logged in to continue')
116
117     def extra_context(self, request, obj):
118         return {
119             "register_form": placeholdized(RegistrationForm(prefix='register')),
120             "register_submit": _('Register'),
121         }
122
123
124 @never_cache
125 def logout_then_redirect(request):
126     auth.logout(request)
127     return HttpResponseRedirect(urlquote_plus(request.GET.get('next', '/'), safe='/?='))
128
129
130 @never_cache
131 def clock(request):
132     """ Provides server UTC time for jquery.countdown,
133     in a format suitable for Date.parse()
134     """
135     return HttpResponse(datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S UTC'))
136
137
138 def publish_plan(request):
139     cache_key = "publish_plan"
140     plan = cache.get(cache_key)
141
142     if plan is None:
143         plan = []
144         try:
145             feed = feedparser.parse(settings.PUBLISH_PLAN_FEED)
146         except:
147             pass
148         else:
149             for i in range(len(feed['entries'])):
150                 plan.append({
151                     'title': feed['entries'][i].title,
152                     'link': feed['entries'][i].link,
153                     })
154         cache.set(cache_key, plan, 1800)
155
156     return render(request, "publish_plan.html", {'plan': plan})
157
158
159 @login_required
160 def user_settings(request):
161     return render(request, "user.html")
162
163
164 @ssi_included(use_lang=False, timeout=1800)
165 def latest_blog_posts(request, feed_url=None, posts_to_show=5):
166     if feed_url is None:
167         feed_url = settings.LATEST_BLOG_POSTS
168     try:
169         feed = feedparser.parse(str(feed_url))
170         posts = []
171         for i in range(posts_to_show):
172             pub_date = feed['entries'][i].published_parsed
173             published = date(pub_date[0], pub_date[1], pub_date[2])
174             posts.append({
175                 'title': feed['entries'][i].title,
176                 'summary': feed['entries'][i].summary,
177                 'link': feed['entries'][i].link,
178                 'date': published,
179                 })
180     except:
181         posts = []
182     return render(request, 'latest_blog_posts.html', {'posts': posts})
183
184
185 @ssi_included(use_lang=False)
186 def widget(request):
187     return render(request, 'widget.html')
188
189
190 class SocialSignupView(SignupView):
191     form_class = SocialSignupForm
192
193
194 def exception_test(request):
195     msg = request.GET.get('msg')
196     if msg:
197         raise Exception('Exception test: %s' % msg)
198     else:
199         raise Exception('Exception test')
200
201
202 def post_test(request):
203     return render(request, 'post_test.html', {'action': '/api/reading/jego-zasady/complete/'})