From 174cf7969627acdc1642f2eda012499b218abac8 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 14 Oct 2022 15:37:22 +0200 Subject: [PATCH] Django 4. --- requirements/requirements.txt | 8 +++----- src/ajaxable/templatetags/ajaxable_tags.py | 6 +++--- src/ajaxable/utils.py | 23 +++++++++++----------- src/catalogue/views.py | 4 ++-- src/club/models.py | 3 +-- src/club/payment_methods.py | 5 ++--- src/paypal/rest.py | 3 +-- src/pdcounter/templatetags/time_tags.py | 8 +++----- src/search/fields.py | 4 ++-- src/social/views.py | 5 +++-- src/waiter/views.py | 3 ++- src/wolnelektury/utils.py | 15 ++++---------- src/wolnelektury/views.py | 4 ++-- 13 files changed, 40 insertions(+), 51 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index b99f18e3b..2dec1cc9b 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -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 diff --git a/src/ajaxable/templatetags/ajaxable_tags.py b/src/ajaxable/templatetags/ajaxable_tags.py index 2d980f278..a9a308d51 100644 --- a/src/ajaxable/templatetags/ajaxable_tags.py +++ b/src/ajaxable/templatetags/ajaxable_tags.py @@ -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), }) diff --git a/src/ajaxable/utils.py b/src/ajaxable/utils.py index 23a350f5f..3a1c4558a 100644 --- a/src/ajaxable/utils.py +++ b/src/ajaxable/utils.py @@ -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 = "" if message: output = "
" + message + "
" + output diff --git a/src/catalogue/views.py b/src/catalogue/views.py index 5a32932a3..12f47a282 100644 --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@ -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): diff --git a/src/club/models.py b/src/club/models.py index 1a78d761c..468622f91 100644 --- a/src/club/models.py +++ b/src/club/models.py @@ -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 diff --git a/src/club/payment_methods.py b/src/club/payment_methods.py index 9fddff3ff..6bb6f8e67 100644 --- a/src/club/payment_methods.py +++ b/src/club/payment_methods.py @@ -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() diff --git a/src/paypal/rest.py b/src/paypal/rest.py index 11693cb8c..e70c67bd4 100644 --- a/src/paypal/rest.py +++ b/src/paypal/rest.py @@ -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, diff --git a/src/pdcounter/templatetags/time_tags.py b/src/pdcounter/templatetags/time_tags.py index 98d516c4b..4597f0429 100644 --- a/src/pdcounter/templatetags/time_tags.py +++ b/src/pdcounter/templatetags/time_tags.py @@ -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 diff --git a/src/search/fields.py b/src/search/fields.py index 10afd5914..07e50d7ba 100644 --- a/src/search/fields.py +++ b/src/search/fields.py @@ -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 diff --git a/src/social/views.py b/src/social/views.py index b7c823373..89661590e 100644 --- a/src/social/views.py +++ b/src/social/views.py @@ -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) diff --git a/src/waiter/views.py b/src/waiter/views.py index b001fef1b..120e32ecb 100644 --- a/src/waiter/views.py +++ b/src/waiter/views.py @@ -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", { diff --git a/src/wolnelektury/utils.py b/src/wolnelektury/utils.py index c994149f6..33bf42cc0 100644 --- a/src/wolnelektury/utils.py +++ b/src/wolnelektury/utils.py @@ -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' diff --git a/src/wolnelektury/views.py b/src/wolnelektury/views.py index 61c55c40e..1855222ed 100644 --- a/src/wolnelektury/views.py +++ b/src/wolnelektury/views.py @@ -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 -- 2.20.1