Django 4.
authorRadek Czajka <rczajka@rczajka.pl>
Fri, 14 Oct 2022 13:37:22 +0000 (15:37 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Fri, 14 Oct 2022 13:37:22 +0000 (15:37 +0200)
13 files changed:
requirements/requirements.txt
src/ajaxable/templatetags/ajaxable_tags.py
src/ajaxable/utils.py
src/catalogue/views.py
src/club/models.py
src/club/payment_methods.py
src/paypal/rest.py
src/pdcounter/templatetags/time_tags.py
src/search/fields.py
src/social/views.py
src/waiter/views.py
src/wolnelektury/utils.py
src/wolnelektury/views.py

index b99f18e..2dec1cc 100644 (file)
@@ -1,7 +1,7 @@
 -i https://py.mdrn.pl/simple/
 
 # django
-Django==3.2.16
+Django==4.0.8
 fnpdjango==0.6
 docutils==0.16
 
@@ -15,7 +15,7 @@ django-allauth==0.51
 django-extensions==3.2.1
 djangorestframework==3.13.1
 djangorestframework-xml==2.0.0
-django-admin-ordering==0.14.0
+django-admin-ordering==0.16
 django-countries==7.3.2
 
 # A version compatible with Django 2.2+, with long help text and editable max_length.
@@ -29,9 +29,7 @@ pyyaml==5.4.1
 
 polib==1.1.1
 
-pytz==2022.2.1
-
-django-honeypot==1.0.2
+django-honeypot==1.0.3
 
 python-fb==0.2
 
index 2d980f2..a9a308d 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django import template
-from django.utils.encoding import force_text
+from django.utils.encoding import force_str
 from django.utils.safestring import mark_safe
 from ajaxable.utils import placeholdized
 
@@ -32,8 +32,8 @@ def pretty_field(field, template=None):
     return mark_safe(template % {
         'errors': field.errors,
         'input': field,
-        'label': ('*' if field.field.required else '') + force_text(field.label),
-        'helptext': force_text(field.help_text),
+        'label': ('*' if field.field.required else '') + force_str(field.label),
+        'helptext': force_str(field.help_text),
     })
 
 
index 23a350f..3a1c455 100644 (file)
@@ -3,21 +3,22 @@
 #
 from functools import wraps
 import json
+from urllib.parse import quote_plus
 
 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
 from django.shortcuts import render
-from django.utils.encoding import force_text
+from django.utils.encoding import force_str
 from django.utils.functional import Promise
-from django.utils.http import urlquote_plus
 from django.utils.translation import gettext_lazy as _
 from django.views.decorators.vary import vary_on_headers
 from honeypot.decorators import verify_honeypot_value
+from wolnelektury.utils import is_ajax
 
 
 class LazyEncoder(json.JSONEncoder):
     def default(self, o):
         if isinstance(o, Promise):
-            return force_text(o)
+            return force_str(o)
         return o
 
 
@@ -38,7 +39,7 @@ def method_decorator(function_decorator):
 
 def require_login(request):
     """Return 403 if request is AJAX. Redirect to login page if not."""
-    if request.is_ajax():
+    if is_ajax(request):
         return HttpResponseForbidden('Not logged in')
     return HttpResponseRedirect('/uzytkownicy/zaloguj')  # next?=request.build_full_path())
 
@@ -104,10 +105,10 @@ class AjaxableFormView:
                     }
                 if add_args:
                     response_data.update(add_args)
-                if not request.is_ajax() and response_data['redirect']:
-                    return HttpResponseRedirect(urlquote_plus(
+                if not is_ajax(request) and response_data['redirect']:
+                    return HttpResponseRedirect(quote_plus(
                         response_data['redirect'], safe='/?=&'))
-            elif request.is_ajax():
+            elif is_ajax(request):
                 # Form was sent with errors. Send them back.
                 if self.form_prefix:
                     errors = {}
@@ -118,17 +119,17 @@ class AjaxableFormView:
                 response_data = {'success': False, 'errors': errors}
             else:
                 response_data = None
-            if request.is_ajax():
+            if is_ajax(request):
                 return HttpResponse(LazyEncoder(ensure_ascii=False).encode(response_data))
         else:
-            if self.POST_login and not request.user.is_authenticated and not request.is_ajax():
+            if self.POST_login and not request.user.is_authenticated and not is_ajax(request):
                 return require_login(request)
 
             form = self.form_class(*form_args, **form_kwargs)
             response_data = None
 
         title = self.title
-        if request.is_ajax():
+        if is_ajax(request):
             template = self.template
         else:
             template = self.full_template
@@ -157,7 +158,7 @@ class AjaxableFormView:
 
     def redirect_or_refresh(self, request, path, message=None):
         """If the form is AJAX, refresh the page. If not, go to `path`."""
-        if request.is_ajax():
+        if is_ajax(request):
             output = "<script>window.location.reload()</script>"
             if message:
                 output = "<div class='normal-text'>" + message + "</div>" + output
index 5a32932..12f47a2 100644 (file)
@@ -4,6 +4,7 @@
 from collections import OrderedDict
 import random
 import re
+from urllib.parse import quote_plus
 
 from django.conf import settings
 from django.template.loader import render_to_string
@@ -12,7 +13,6 @@ from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpRespons
 from django.urls import reverse
 from django.db.models import Q, QuerySet
 from django.contrib.auth.decorators import login_required, user_passes_test
-from django.utils.http import urlquote_plus
 from django.utils import translation
 from django.utils.translation import gettext as _, gettext_lazy
 from django.views.decorators.cache import never_cache
@@ -416,7 +416,7 @@ def download_zip(request, file_format=None, media_format=None, slug=None):
         url = book.zip_audiobooks(media_format)
     else:
         raise Http404('No format specified for zip package')
-    return HttpResponseRedirect(urlquote_plus(settings.MEDIA_URL + url, safe='/?='))
+    return HttpResponseRedirect(quote_plus(settings.MEDIA_URL + url, safe='/?='))
 
 
 class CustomPDFFormView(AjaxableFormView):
index 1a78d76..468622f 100644 (file)
@@ -11,10 +11,9 @@ from django.core.mail import send_mail, EmailMessage
 from django.urls import reverse
 from django.db import models
 from django import template
-from django.utils.timezone import now
+from django.utils.timezone import now, utc
 from django.utils.translation import gettext_lazy as _, ngettext, gettext, get_language
 from django_countries.fields import CountryField
-from pytz import utc
 from catalogue.utils import get_random_hash
 from messaging.states import Level
 from reporting.utils import render_to_pdf
index 9fddff3..6bb6f8e 100644 (file)
@@ -159,9 +159,8 @@ class PayPal(PaymentMethod):
         return agreement_approval_url(schedule.amount, schedule.key, app=app)
 
     def pay(self, request, schedule):
-        from datetime import date, timedelta, datetime
-        from pytz import utc
-        tomorrow = datetime(*(date.today() + timedelta(2)).timetuple()[:3], tzinfo=utc)
+        from datetime import date, timedelta, datetime, timezone
+        tomorrow = datetime(*(date.today() + timedelta(2)).timetuple()[:3], tzinfo=timezone.utc)
         any_active = False
         for ba in schedule.billingagreement_set.all():
             active = ba.check_agreement()
index 11693cb..e70c67b 100644 (file)
@@ -4,7 +4,6 @@
 from datetime import date, datetime, timedelta
 from decimal import Decimal
 import paypalrestsdk
-import pytz
 from django.contrib.sites.models import Site
 from django.urls import reverse
 from django.utils import timezone
@@ -70,7 +69,7 @@ def create_agreement(amount, key, app=False):
         plan_id = create_plan(amount)
     else:
         plan_id = plan.plan_id
-    start = (timezone.now() + timedelta(0, 3600*24)).astimezone(pytz.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
+    start = (timezone.now() + timedelta(0, 3600*24)).astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
     billing_agreement = paypalrestsdk.BillingAgreement({
         "name": "Subskrypcja klubu WL",
         "description": "Stałe wsparcie Wolnych Lektur kwotą %s złotych" % amount,
index 98d516c..4597f04 100644 (file)
@@ -2,7 +2,6 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import datetime
-import pytz
 from django.conf import settings
 from django import template
 from django.utils import timezone
@@ -20,10 +19,9 @@ def date_to_utc(date, day_end=False):
     """
     if day_end:
         date += datetime.timedelta(1)
-    localtime = datetime.datetime.combine(date, datetime.time(0, 0))
-    return timezone.utc.normalize(
-        pytz.timezone(settings.TIME_ZONE).localize(localtime)
-    )
+
+    localtime = datetime.datetime.combine(date, datetime.time(0, 0), timezone.get_current_timezone())
+    return timezone.localtime(localtime, timezone.utc)
 
 
 @register.filter
index 10afd59..07e50d7 100644 (file)
@@ -3,7 +3,7 @@
 #
 from django import forms
 from django.forms.utils import flatatt
-from django.utils.encoding import smart_text
+from django.utils.encoding import smart_str
 from django.utils.safestring import mark_safe
 from json import dumps
 
@@ -20,7 +20,7 @@ class JQueryAutoCompleteWidget(forms.TextInput):
         final_attrs = self.build_attrs(self.attrs, attrs)
         final_attrs["name"] = name
         if value:
-            final_attrs['value'] = smart_text(value)
+            final_attrs['value'] = smart_str(value)
 
         if 'id' not in self.attrs:
             final_attrs['id'] = 'id_%s' % name
index b7c8233..8966159 100644 (file)
@@ -10,6 +10,7 @@ from ajaxable.utils import AjaxableFormView
 
 from catalogue.models import Book
 from social import forms
+from wolnelektury.utils import is_ajax
 
 
 # ====================
@@ -25,7 +26,7 @@ def like_book(request, slug):
 
     book.like(request.user)
 
-    if request.is_ajax():
+    if is_ajax(request):
         return JsonResponse({"success": True, "msg": "ok", "like": True})
     else:
         return redirect(book)
@@ -39,7 +40,7 @@ def unlike_book(request, slug):
 
     book.unlike(request.user)
 
-    if request.is_ajax():
+    if is_ajax(request):
         return JsonResponse({"success": True, "msg": "ok", "like": False})
     else:
         return redirect(book)
index b001fef..120e32e 100644 (file)
@@ -7,6 +7,7 @@ from waiter.settings import WAITER_URL
 from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponse
 from django.views.decorators.cache import never_cache
+from wolnelektury.utils import is_ajax
 
 
 @never_cache
@@ -18,7 +19,7 @@ def wait(request, path):
         file_url = None
         waiting = get_object_or_404(WaitedFile, path=path)
 
-    if request.is_ajax():
+    if is_ajax(request):
         return HttpResponse(file_url)
     else:
         return render(request, "waiter/wait.html", {
index c994149..33bf42c 100644 (file)
@@ -8,7 +8,6 @@ from inspect import getargspec
 from io import BytesIO
 import json
 import os
-import pytz
 import re
 
 from django.conf import settings
@@ -17,22 +16,12 @@ from django.core.cache import cache
 from django.core.mail import send_mail
 from django.http import HttpResponse
 from django.template.loader import render_to_string
-from django.utils import timezone
 from django.utils.translation import get_language
 from django.conf import settings
 from django.utils.safestring import mark_safe
 from django.utils.translation import gettext as _
 
 
-tz = pytz.timezone(settings.TIME_ZONE)
-
-
-def localtime_to_utc(localtime):
-    return timezone.utc.normalize(
-        tz.localize(localtime)
-    )
-
-
 def utc_for_js(dt):
     return dt.strftime('%Y/%m/%d %H:%M:%S UTC')
 
@@ -211,3 +200,7 @@ class YesNoFilter(admin.SimpleListFilter):
             return queryset.filter(self.q)
         elif self.value() == 'no':
             return queryset.exclude(self.q)
+
+
+def is_ajax(request):
+    return request.headers.get('x-requested-with') == 'XMLHttpRequest'
index 61c55c4..1855222 100644 (file)
@@ -2,6 +2,7 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from datetime import date, datetime
+from urllib.parse import quote_plus
 import feedparser
 from allauth.socialaccount.views import SignupView
 
@@ -12,7 +13,6 @@ from django.contrib.auth.forms import AuthenticationForm
 from django.core.cache import cache
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import render
-from django.utils.http import urlquote_plus
 from django.utils.translation import gettext_lazy as _
 from django.views.decorators.cache import never_cache
 
@@ -131,7 +131,7 @@ class LoginRegisterFormView(LoginFormView):
 @never_cache
 def logout_then_redirect(request):
     auth.logout(request)
-    return HttpResponseRedirect(urlquote_plus(request.GET.get('next', '/'), safe='/?='))
+    return HttpResponseRedirect(quote_plus(request.GET.get('next', '/'), safe='/?='))
 
 
 @never_cache