1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 from datetime import date, datetime
5 from urllib.parse import quote_plus
7 from allauth.socialaccount.views import SignupView
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.contrib.auth.views import LoginView
14 from django.core.cache import cache
15 from django.views.generic import FormView
16 from django.http import HttpResponse, HttpResponseRedirect
17 from django.shortcuts import render
18 from django.utils.translation import gettext_lazy as _
19 from django.views.decorators.cache import never_cache
21 from ajaxable.utils import AjaxableFormView
22 from ajaxable.utils import placeholdized
23 from catalogue.models import Book, Collection, Tag, Fragment
25 from social.utils import get_or_choose_cite
26 from wolnelektury.forms import RegistrationForm, SocialSignupForm, WLAuthenticationForm
29 def main_page_2022(request):
31 ctx['last_published'] = Book.objects.exclude(cover_clean='').filter(findable=True, parent=None).order_by('-created_at')[:10]
32 ctx['recommended_collection'] = Collection.objects.filter(listed=True, role='recommend').order_by('?').first()
33 ctx['ambassadors'] = club.models.Ambassador.objects.all().order_by('?')
34 ctx['widget'] = settings.WIDGETS.get(request.GET.get('w'))
35 return render(request, '2022/main_page.html', ctx)
38 def main_page(request):
39 if request.GET.get('w') in settings.WIDGETS:
40 request.EXPERIMENTS['layout'].override(True)
42 if request.EXPERIMENTS['layout'].value:
43 return main_page_2022(request)
46 'last_published': Book.objects.exclude(cover_thumb='').filter(findable=True, parent=None).order_by('-created_at')[:6],
50 # FIXME: find this theme and books properly.
51 if Fragment.objects.exists():
53 ctx['theme'] = Tag.objects.filter(category='theme').order_by('?')[:1][0]
54 tf = Fragment.tagged.with_any([ctx['theme']]).select_related('book').filter(book__findable=True).order_by('?')[:100]
57 ctx['theme_fragment'] = tf[0]
59 if f.book not in ctx['theme_books']:
60 ctx['theme_books'].append(f.book)
61 if len(ctx['theme_books']) == 3:
65 # Choose collections for main.
66 ctx['collections'] = Collection.objects.filter(listed=True).order_by('?')[:4]
70 recommended_collection = None
71 for recommended in Collection.objects.filter(listed=True, role='recommend').order_by('?'):
72 if recommended_collection is None:
73 recommended_collection = recommended
74 books = list(recommended.get_books().exclude(id__in=[b.id for b in best]).order_by('?')[:best_places])
76 best_places -= len(books)
79 ctx['recommended_collection'] = recommended_collection
83 Book.objects.filter(findable=True).exclude(id__in=[b.id for b in best]).order_by('?')[:best_places]
88 return render(request, "main_page.html", ctx)
91 class WLLoginView(LoginView):
92 form_class = WLAuthenticationForm
95 wl_login_view = WLLoginView.as_view()
98 class LoginFormView(AjaxableFormView):
99 form_class = AuthenticationForm
100 template = "auth/login.html"
103 submit = _('Sign in')
106 def __call__(self, request):
107 if request.EXPERIMENTS['layout'].value:
108 return wl_login_view(request)
110 if request.user.is_authenticated:
111 return self.redirect_or_refresh(
113 message=_('Already logged in as user %(user)s', ) % {'user': request.user.username})
114 return super(LoginFormView, self).__call__(request)
116 def success(self, form, request):
117 auth.login(request, form.get_user())
120 class WLRegisterView(FormView):
121 form_class = RegistrationForm
122 template_name = 'registration/register.html'
124 def form_valid(self, form):
126 user = auth.authenticate(
127 username=form.cleaned_data['username'],
128 password=form.cleaned_data['password1']
130 auth.login(self.request, user)
131 return HttpResponseRedirect(quote_plus(self.request.GET.get('next', '/'), safe='/?='))
133 wl_register_view = WLRegisterView.as_view()
136 class RegisterFormView(AjaxableFormView):
137 form_class = RegistrationForm
138 template = "auth/register.html"
140 title = _('Register')
141 submit = _('Register')
143 form_prefix = 'register'
146 def __call__(self, request):
147 if request.EXPERIMENTS['layout'].value:
148 return wl_register_view(request)
150 if request.user.is_authenticated:
151 return self.redirect_or_refresh(
153 message=_('Already logged in as user %(user)s', ) % {'user': request.user.username})
154 return super(RegisterFormView, self).__call__(request)
156 def success(self, form, request):
158 user = auth.authenticate(
159 username=form.cleaned_data['username'],
160 password=form.cleaned_data['password1']
162 auth.login(request, user)
165 class LoginRegisterFormView(LoginFormView):
166 template = 'auth/login_register.html'
167 title = _('You have to be logged in to continue')
169 def extra_context(self, request, obj):
171 "register_form": placeholdized(RegistrationForm(prefix='register')),
172 "register_submit": _('Register'),
177 def logout_then_redirect(request):
179 return HttpResponseRedirect(quote_plus(request.GET.get('next', '/'), safe='/?='))
184 """ Provides server UTC time for jquery.countdown,
185 in a format suitable for Date.parse()
187 return HttpResponse(datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S UTC'))
190 def publish_plan(request):
191 cache_key = "publish_plan"
192 plan = cache.get(cache_key)
197 feed = feedparser.parse(settings.PUBLISH_PLAN_FEED)
201 for i in range(len(feed['entries'])):
203 'title': feed['entries'][i].title,
204 'link': feed['entries'][i].link,
206 cache.set(cache_key, plan, 1800)
208 return render(request, "publish_plan.html", {'plan': plan})
212 def user_settings(request):
213 return render(request, "user.html")
217 return render(request, 'widget.html')
220 class SocialSignupView(SignupView):
221 form_class = SocialSignupForm
224 def exception_test(request):
225 msg = request.GET.get('msg')
227 raise Exception('Exception test: %s' % msg)
229 raise Exception('Exception test')
232 def post_test(request):
233 return render(request, 'post_test.html', {'action': '/api/reading/jego-zasady/complete/'})