diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index d0eb1d8..c619d32 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -26,7 +26,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.7, 3.8, 3.9 ] + python-version: [ 3.8, 3.9 ] steps: - name: Start MySQL @@ -65,7 +65,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.7, 3.8, 3.9 ] + python-version: [ 3.8, 3.9 ] steps: - name: Start MySQL diff --git a/accounts/urls.py b/accounts/urls.py index 0dcdc73..e11dd73 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import include, re_path from django.urls import path from . import views @@ -6,23 +6,23 @@ from .forms import LoginForm app_name = "accounts" -urlpatterns = [url(r'^login/$', +urlpatterns = [re_path(r'^login/$', views.LoginView.as_view(success_url='/'), name='login', kwargs={'authentication_form': LoginForm}), - url(r'^register/$', + re_path(r'^register/$', views.RegisterView.as_view(success_url="/"), name='register'), - url(r'^logout/$', + re_path(r'^logout/$', views.LogoutView.as_view(), name='logout'), path(r'account/result.html', views.account_result, name='result'), - url(r'^forget_password/$', + re_path(r'^forget_password/$', views.ForgetPasswordView.as_view(), name='forget_password'), - url(r'^forget_password_code/$', + re_path(r'^forget_password_code/$', views.ForgetPasswordEmailCode.as_view(), name='forget_password_code'), ] diff --git a/accounts/views.py b/accounts/views.py index 06803c7..06b6fd7 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -14,7 +14,7 @@ from django.shortcuts import get_object_or_404 from django.shortcuts import render from django.urls import reverse from django.utils.decorators import method_decorator -from django.utils.http import is_safe_url +from django.utils.http import url_has_allowed_host_and_scheme from django.views import View from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_protect @@ -135,7 +135,7 @@ class LoginView(FormView): def get_success_url(self): redirect_to = self.request.POST.get(self.redirect_field_name) - if not is_safe_url( + if not url_has_allowed_host_and_scheme( url=redirect_to, allowed_hosts=[ self.request.get_host()]): redirect_to = self.success_url diff --git a/blog/admin.py b/blog/admin.py index f812dc6..9a07b3d 100644 --- a/blog/admin.py +++ b/blog/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin from django.contrib.auth import get_user_model from django.urls import reverse from django.utils.html import format_html -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ # Register your models here. from .models import Article diff --git a/djangoblog/blog_signals.py b/djangoblog/blog_signals.py index 525d45d..00ecff1 100644 --- a/djangoblog/blog_signals.py +++ b/djangoblog/blog_signals.py @@ -18,9 +18,9 @@ from oauth.models import OAuthUser logger = logging.getLogger(__name__) -oauth_user_login_signal = django.dispatch.Signal(providing_args=['id']) +oauth_user_login_signal = django.dispatch.Signal(['id']) send_email_signal = django.dispatch.Signal( - providing_args=['emailto', 'title', 'content']) + ['emailto', 'title', 'content']) @receiver(send_email_signal) diff --git a/djangoblog/elasticsearch_backend.py b/djangoblog/elasticsearch_backend.py index 9120589..5f875f4 100644 --- a/djangoblog/elasticsearch_backend.py +++ b/djangoblog/elasticsearch_backend.py @@ -1,4 +1,4 @@ -from django.utils.encoding import force_text +from django.utils.encoding import force_str from elasticsearch_dsl import Q from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, log_query from haystack.models import SearchResult @@ -98,9 +98,9 @@ class ElasticSearchBackend(BaseSearchBackend): class ElasticSearchQuery(BaseSearchQuery): def _convert_datetime(self, date): if hasattr(date, 'hour'): - return force_text(date.strftime('%Y%m%d%H%M%S')) + return force_str(date.strftime('%Y%m%d%H%M%S')) else: - return force_text(date.strftime('%Y%m%d000000')) + return force_str(date.strftime('%Y%m%d000000')) def clean(self, query_fragment): """ diff --git a/djangoblog/logentryadmin.py b/djangoblog/logentryadmin.py index 009ab9d..9623324 100644 --- a/djangoblog/logentryadmin.py +++ b/djangoblog/logentryadmin.py @@ -2,10 +2,10 @@ from django.contrib import admin from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION from django.contrib.contenttypes.models import ContentType from django.urls import reverse, NoReverseMatch -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.html import escape from django.utils.safestring import mark_safe -from django.utils.translation import pgettext_lazy, ugettext_lazy as _ +from django.utils.translation import pgettext_lazy, gettext_lazy as _ action_names = { ADDITION: pgettext_lazy('logentry_admin:action_type', 'Addition'), @@ -96,7 +96,7 @@ class LogEntryAdmin(admin.ModelAdmin): def user_link(self, obj): content_type = ContentType.objects.get_for_model(type(obj.user)) - user_link = escape(force_text(obj.user)) + user_link = escape(force_str(obj.user)) try: # try returning an actual link instead of object repr string url = reverse( diff --git a/djangoblog/urls.py b/djangoblog/urls.py index c0d96fa..6d88345 100644 --- a/djangoblog/urls.py +++ b/djangoblog/urls.py @@ -14,7 +14,7 @@ Including another URLconf 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf import settings -from django.conf.urls import url +from django.urls import include, re_path from django.conf.urls.static import static from django.contrib.sitemaps.views import sitemap from django.urls import include @@ -36,19 +36,19 @@ handler404 = 'blog.views.page_not_found_view' handler500 = 'blog.views.server_error_view' handle403 = 'blog.views.permission_denied_view' urlpatterns = [ - url(r'^admin/', admin_site.urls), - url(r'', include('blog.urls', namespace='blog')), - url(r'mdeditor/', include('mdeditor.urls')), - url(r'', include('comments.urls', namespace='comment')), - url(r'', include('accounts.urls', namespace='account')), - url(r'', include('oauth.urls', namespace='oauth')), - url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, + re_path(r'^admin/', admin_site.urls), + re_path(r'', include('blog.urls', namespace='blog')), + re_path(r'mdeditor/', include('mdeditor.urls')), + re_path(r'', include('comments.urls', namespace='comment')), + re_path(r'', include('accounts.urls', namespace='account')), + re_path(r'', include('oauth.urls', namespace='oauth')), + re_path(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'), - url(r'^feed/$', DjangoBlogFeed()), - url(r'^rss/$', DjangoBlogFeed()), - url(r'^search', include('haystack.urls'), name='search'), - url(r'', include('servermanager.urls', namespace='servermanager')), - url(r'', include('owntracks.urls', namespace='owntracks')) + re_path(r'^feed/$', DjangoBlogFeed()), + re_path(r'^rss/$', DjangoBlogFeed()), + re_path(r'^search', include('haystack.urls'), name='search'), + re_path(r'', include('servermanager.urls', namespace='servermanager')), + re_path(r'', include('owntracks.urls', namespace='owntracks')) ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, diff --git a/djangoblog/whoosh_cn_backend.py b/djangoblog/whoosh_cn_backend.py index f246c81..c285cc2 100644 --- a/djangoblog/whoosh_cn_backend.py +++ b/djangoblog/whoosh_cn_backend.py @@ -13,7 +13,7 @@ import six from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.utils.datetime_safe import datetime -from django.utils.encoding import force_text +from django.utils.encoding import force_str from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, EmptyResults, log_query from haystack.constants import DJANGO_CT, DJANGO_ID, ID from haystack.exceptions import MissingDependency, SearchBackendError, SkipDocument @@ -376,7 +376,7 @@ class WhooshSearchBackend(BaseSearchBackend): 'hits': 0, } - query_string = force_text(query_string) + query_string = force_str(query_string) # A one-character query (non-wildcard) gets nabbed by a stopwords # filter and should yield zero results. @@ -467,7 +467,7 @@ class WhooshSearchBackend(BaseSearchBackend): for nq in narrow_queries: recent_narrowed_results = narrow_searcher.search( - self.parser.parse(force_text(nq)), limit=None) + self.parser.parse(force_str(nq)), limit=None) if len(recent_narrowed_results) <= 0: return { @@ -614,7 +614,7 @@ class WhooshSearchBackend(BaseSearchBackend): for nq in narrow_queries: recent_narrowed_results = narrow_searcher.search( - self.parser.parse(force_text(nq)), limit=None) + self.parser.parse(force_str(nq)), limit=None) if len(recent_narrowed_results) <= 0: return { @@ -771,7 +771,7 @@ class WhooshSearchBackend(BaseSearchBackend): spelling_suggestion = None reader = self.index.reader() corrector = reader.corrector(self.content_field_name) - cleaned_query = force_text(query_string) + cleaned_query = force_str(query_string) if not query_string: return spelling_suggestion @@ -811,12 +811,12 @@ class WhooshSearchBackend(BaseSearchBackend): else: value = 'false' elif isinstance(value, (list, tuple)): - value = u','.join([force_text(v) for v in value]) + value = u','.join([force_str(v) for v in value]) elif isinstance(value, (six.integer_types, float)): # Leave it alone. pass else: - value = force_text(value) + value = force_str(value) return value def _to_python(self, value): @@ -873,9 +873,9 @@ class WhooshSearchBackend(BaseSearchBackend): class WhooshSearchQuery(BaseSearchQuery): def _convert_datetime(self, date): if hasattr(date, 'hour'): - return force_text(date.strftime('%Y%m%d%H%M%S')) + return force_str(date.strftime('%Y%m%d%H%M%S')) else: - return force_text(date.strftime('%Y%m%d000000')) + return force_str(date.strftime('%Y%m%d000000')) def clean(self, query_fragment): """ diff --git a/requirements.txt b/requirements.txt index 912f257..62dce71 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,28 @@ -coverage==6.2 +coverage==6.3.2 bleach==4.1.0 -Django==3.2.12 +Django==4.0.3 django-compressor==3.1 -django-haystack==3.1.1 +django-haystack==3.2.dev0 django-ipware==4.0.2 -django-mdeditor==0.1.18 -django-uuslug==1.2.0 +django-mdeditor==0.1.20 +django-uuslug==2.0.0 elasticsearch==7.16.1 elasticsearch-dsl==7.4.0 gevent==21.12.0 jieba==0.42.1 -jsonpickle==2.0.0 +jsonpickle==2.1.0 Markdown==3.3.6 mysqlclient==2.1.0 -Pillow==9.0.0 -Pygments==2.10.0 +Pillow==9.0.1 +Pygments==2.11.2 python-logstash==0.4.6 python-memcached==1.59 -python-slugify==5.0.2 -pytz==2021.3 +python-slugify==6.1.1 +pytz==2022.1 raven==6.10.0 -requests==2.26.0 -urllib3==1.26.7 +requests==2.27.1 +urllib3==1.26.9 WeRoBot==1.13.1 Whoosh==2.7.4 user-agents==2.2.0 +redis==4.1.4