Fixed: ugettext has been deprecated

Fixed: Deprecatios for Django 4.0
Changed: path instead of url_path
Added: fiaxateranking command
This commit is contained in:
2023-07-20 22:56:13 +02:00
parent fbfabb982f
commit ef00fc25f7
32 changed files with 266 additions and 252 deletions

View File

@@ -8,7 +8,7 @@ django-compressor
django-extra-views
django-markdown
django-recaptcha
git+https://github.com/SmileyChris/easy-thumbnails.git
easy_thumbnails[svg]
icalendar
openpyxl
markdown

View File

@@ -19,9 +19,9 @@ def content_menus(request):
:param request: a Django request object
:return: a dict with the template variables mentioned above
"""
current_page = models.Page()
current_top_page = models.Page()
current_path = request.path_info[1:request.path_info.rfind('.')]
current_page: models.Page = models.Page.objects.get(slug='index')
current_top_page: models.Page = models.Page.objects.get(slug='index')
current_path: str = request.path_info[1:request.path_info.rfind('.')]
# erzeuge das Top-Level Menü
top_level_pages = cache.get('top_level_pages')

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.content\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-06-09 22:00+0200\n"
"PO-Revision-Date: 2018-01-12 15:25+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Deutsch <>\n"
@@ -206,7 +206,7 @@ msgstr "Erstellt am"
msgid "share on"
msgstr "Teile auf"
#: templates/content/article_detail.html:48 views.py:156
#: templates/content/article_detail.html:48 views.py:159
msgid "Edit Article"
msgstr "Artikel bearbeiten"
@@ -249,16 +249,16 @@ msgstr "HTML spezifisch"
msgid "This Category does not exist."
msgstr "Diese Kategorie existiert nicht."
#: views.py:157
#: views.py:160
msgid "Create Article"
msgstr "Artikel erstellen"
#: views.py:237
#: views.py:240
#, python-format
msgid "No Page found matching the Path %s"
msgstr "Keine Seite unter dem Pfad %s gefunden"
#: views.py:266
#: views.py:269
#, python-format
msgid "No PDF Document found matching the Path %s"
msgstr "Kein PDF Dokument unter dem Pfad %s gefunden."

View File

@@ -216,7 +216,7 @@ class Page(models.Model):
blank=True,
null=True,
related_name='subpages',
on_delete=models.SET_NULL
on_delete=models.CASCADE
)
position = models.PositiveSmallIntegerField(
blank=True,

View File

@@ -4,26 +4,19 @@ Created on 03.10.2011
@author: christian
"""
from django.conf.urls import url
from django.urls import path
from .views import ArticleArchiveIndex, ArticleForm, ArticleYearArchive, \
ArticleMonthArchive, ArticleDetail
urlpatterns = [
url(r'^$', ArticleArchiveIndex.as_view(), name='article-archive'),
url(r'^add/$', ArticleForm.as_view(), name='add-article'),
url(r'^edit/(?P<pk>[\d]+)/$', ArticleForm.as_view(), name='edit-article'),
url(r'^(?P<year>[\d]{4})/$', ArticleYearArchive.as_view(),
name='article-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$', ArticleMonthArchive.as_view(),
name='article-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<slug>[\-\d\w]+)/$',
ArticleDetail.as_view(), name='show-article'),
url(r'^(?P<category>[\-\d\w]+)/$', ArticleArchiveIndex.as_view(),
name='article-archive'),
url(r'^(?P<category>[\-\d\w]+)/(?P<year>[\d]{4})/$',
ArticleYearArchive.as_view(), name='article-archive'),
url(r'^(?P<category>[\-\d\w]+)/(?P<year>[\d]{4})/(?P<month>[\d]+)/$',
ArticleMonthArchive.as_view(), name='article-archive'),
path("", ArticleArchiveIndex.as_view(), name='article-archive'),
path('add/', ArticleForm.as_view(), name='add-article'),
path('edit/<int:pk>/', ArticleForm.as_view(), name='edit-article'),
path('<int:year>/', ArticleYearArchive.as_view(), name='article-archive'),
path('<int:year>/<int:month>/', ArticleMonthArchive.as_view(), name='article-archive'),
path('<int:year>/<int:month>/<slug:slug>/', ArticleDetail.as_view(), name='show-article'),
path('<slug:category>/', ArticleArchiveIndex.as_view(), name='article-archive'),
path('<slug:category>/<int:year>/', ArticleYearArchive.as_view(), name='article-archive'),
path('<slug:category>/<int:year>/<int:month>/', ArticleMonthArchive.as_view(), name='article-archive'),
]

View File

@@ -56,7 +56,7 @@
{% if not active_category %} class="active" {% endif %}>{% trans 'All Categories' %}</a></li>
{% for category in categories %}
<li><a href="{% url 'article-archive' category=category.slug %}"
{% ifequal category.slug active_category.slug %} class="active"{% endifequal %}>{{ category.name }}</a></li>
{% if category.slug == active_category.slug %} class="active"{% endif %}>{{ category.name }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@@ -1,18 +1,13 @@
""" urls for the event gallery part of the events app. """
from django.conf.urls import url
from django.urls import path
from . import views
urlpatterns = [
url(r'^$', views.EventGallery.as_view(), name='event-gallery'),
url(r'^(?P<event>[\d]+)/$', views.EventPhotoList.as_view(),
name='event-photo-list'),
url(r'^(?P<event>[\d]+)/upload/$', views.EventPhotoUpload.as_view(),
name='event-photo-upload'),
url(r'^(?P<event>[\d]+)/(?P<pk>[\d]+)/$', views.EventPhoto.as_view(),
name='event-photo'),
url(r'^delete/(?P<pk>[\d]+)/$', views.DeleteEventPhoto.as_view(),
name='delete-event-photo'),
url(r'^upload/$', views.EventPhotoUpload.as_view(),
name='event-photo-upload'),
path("", views.EventGallery.as_view(), name='event-gallery'),
path('<int:event>/', views.EventPhotoList.as_view(), name='event-photo-list'),
path('<int:event>/upload/', views.EventPhotoUpload.as_view(), name='event-photo-upload'),
path('<int:event>/<int:pk>/', views.EventPhoto.as_view(), name='event-photo'),
path('delete/<int:pk>/', views.DeleteEventPhoto.as_view(), name='delete-event-photo'),
path('upload/', views.EventPhotoUpload.as_view(), name='event-photo-upload'),
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.events\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-06-11 10:15+0200\n"
"PO-Revision-Date: 2018-01-12 15:25+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -23,19 +23,19 @@ msgstr ""
msgid "Event Series"
msgstr "Veranstaltungsreihen"
#: forms.py:17
#: forms.py:38
msgid "Images"
msgstr "Bilder"
#: forms.py:46
#: forms.py:61
msgid "start"
msgstr "Beginn"
#: forms.py:49
#: forms.py:64
msgid "end"
msgstr "Ende"
#: mixins.py:76
#: mixins.py:86
msgid "Event does not exist"
msgstr "Veranstaltung gibt es nicht"
@@ -242,7 +242,7 @@ msgid "Show on Google Maps"
msgstr "Auf Google Maps zeigen"
#: templates/events/event_detail.html:127 templates/events/event_form.html:9
#: views.py:62
#: views.py:63
msgid "Edit Event"
msgstr "Termin bearbeiten"
@@ -250,7 +250,7 @@ msgstr "Termin bearbeiten"
msgid "Add Dates"
msgstr "Termine hinzufügen"
#: templates/events/event_form.html:9 templates/events/page.html:9 views.py:64
#: templates/events/event_form.html:9 templates/events/page.html:9 views.py:65
msgid "Add Event"
msgstr "Neuer Termin"

View File

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
from django.db import migrations, models
import datetime
from django.utils.timezone import utc
from datetime import timezone
class Migration(migrations.Migration):
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
model_name='event',
name='date_modified',
field=models.DateTimeField(default=datetime.datetime(
2016, 10, 12, 20, 24, 39, 910492, tzinfo=utc), verbose_name='latest updated at', auto_now=True),
2016, 10, 12, 20, 24, 39, 910492, tzinfo=timezone.utc), verbose_name='latest updated at', auto_now=True),
preserve_default=False,
),
migrations.AddField(
@@ -36,7 +36,7 @@ class Migration(migrations.Migration):
model_name='location',
name='date_modified',
field=models.DateTimeField(default=datetime.datetime(
2016, 10, 12, 20, 24, 44, 566305, tzinfo=utc), verbose_name='latest updated at', auto_now=True),
2016, 10, 12, 20, 24, 44, 566305, tzinfo=timezone.utc), verbose_name='latest updated at', auto_now=True),
preserve_default=False,
),
migrations.AddField(
@@ -49,7 +49,7 @@ class Migration(migrations.Migration):
model_name='photo',
name='date_modified',
field=models.DateTimeField(default=datetime.datetime(
2016, 10, 12, 20, 24, 50, 509970, tzinfo=utc), verbose_name='latest updated at', auto_now=True),
2016, 10, 12, 20, 24, 50, 509970, tzinfo=timezone.utc), verbose_name='latest updated at', auto_now=True),
preserve_default=False,
),
]

View File

@@ -1,22 +1,16 @@
"""URLS to access upcoming events and the event archive."""
from django.conf.urls import url
from django.urls import path
from django.views.generic import RedirectView
from . import views
urlpatterns = [
url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)),
url(r'^(?P<year>[\d]{4})/$', views.EventArchiveYear.as_view(),
name='event-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$',
views.EventArchiveMonth.as_view(),
name='event-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/$',
views.EventDetail.as_view(), name='event-detail'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/add_dates/$',
views.EventSeriesForm.as_view(), name='eventseries-form'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/edit/$',
views.EventForm.as_view(), name='event-form'),
url(r'^add/$', views.EventForm.as_view(), name='event-form'),
url(r'^archive/$', views.EventArchiveIndex.as_view(), name='event-archive'),
url(r'^upcoming/$', views.UpcomingEvents.as_view(), name='upcoming-events'),
path("", RedirectView.as_view(url='/events/upcoming/', permanent=True)),
path('<int:year>/', views.EventArchiveYear.as_view(), name='event-archive'),
path('<int:year>/<int:month>/', views.EventArchiveMonth.as_view(), name='event-archive'),
path('<int:year>/<int:month>/<int:pk>/', views.EventDetail.as_view(), name='event-detail'),
path('<int:year>/<int:month>/<int:pk>/add_dates/', views.EventSeriesForm.as_view(), name='eventseries-form'),
path('<int:year>/<int:month>/<int:pk>/edit/', views.EventForm.as_view(), name='event-form'),
path('add/', views.EventForm.as_view(), name='event-form'),
path('archive/', views.EventArchiveIndex.as_view(), name='event-archive'),
path('upcoming/', views.UpcomingEvents.as_view(), name='upcoming-events'),
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.utils\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-07-20 21:25+0200\n"
"PO-Revision-Date: 2018-12-30 11:14+0105\n"
"Last-Translator: b' <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -19,11 +19,11 @@ msgstr ""
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.9.0\n"
#: settings.py:140
#: settings.py:144
msgid "German"
msgstr "Deutsch"
#: settings.py:140
#: settings.py:144
msgid "English"
msgstr "Englisch"
@@ -192,8 +192,8 @@ msgid ""
" From <a href=\"%(user_link)s\">%(author)s</a> in\n"
" <a href=\"%(comment_link)s\">&ldquo;%(object)s&rdquo;</a>\n"
" since\n"
" <time datetime=\"%(submit_date|date:'Y-m-d\\TH:i:sO')s\">"
"%(since)s</time>\n"
" <time "
"datetime=\"%(submit_date|date:'Y-m-d\\TH:i:sO')s\">%(since)s</time>\n"
" "
msgstr ""
"\n"

View File

@@ -133,6 +133,10 @@ LOGIN_URL = '/membership/login/'
LOGIN_ERROR_URL = '/membership/login/error/'
LOGIN_REDIRECT_URL = '/users/'
# Set the primarykey handing to old django style
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# Localization
USE_I18N = True
USE_L10N = True

View File

@@ -46,12 +46,12 @@
<ul class="main_menu">
{% for item in top_menu_items %}
<li><a href="{{item.get_absolute_url}}" title="{{ item.title }}"
class="{%if item.active %}active{% endif %}">{{item.menu_name}}</a>
class="{% if item.active %}active{% endif %}">{{item.menu_name}}</a>
{% if item.subpages.all %}
<ul class="main_dropdown">
{% for subpage in item.subpages.all %}<li><a
href="{{subpage.get_absolute_url}}"
{% ifequal subpage current_page %}class="active"{% endifequal %}>{{subpage.menu_name}}</a></li>
{% if subpage == current_page %}class="active"{% endif %}>{{subpage.menu_name}}</a></li>
{% endfor %}
</ul>
{% endif %}
@@ -116,9 +116,9 @@
{% block navigation %}{% if current_top_page.subpages.count %}
<ul id="navigation">
<li><a href="{{current_top_page.get_absolute_url}}"
class="{% ifequal current_page current_top_page %}{% endifequal %}">{{current_top_page.menu_name}}</a></li>
class="{% if current_page == current_top_page %}{% endif %}">{{current_top_page.menu_name}}</a></li>
{% for subpage in current_top_page.subpages.all %}
<li><a href="{{subpage.get_absolute_url}}" class="{% ifequal subpage current_page %}active{% endifequal %}">{{subpage.menu_name}}</a>
<li><a href="{{subpage.get_absolute_url}}" class="{% if subpage == current_page %}active{% endif %}">{{subpage.menu_name}}</a>
</li>
{% endfor %}
{% block additional_nav_elements %}{% endblock %}
@@ -169,8 +169,8 @@
<select name="language" id="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{language.code}}" {% ifequal language.code LANGUAGE_CODE %}
selected="selected" {% endifequal %}>{{ language.name_local }} ({{ language.code }})
<option value="{{language.code}}" {% if language.code == LANGUAGE_CODE %}
selected="selected" {% endif %}>{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>

View File

@@ -9,7 +9,7 @@
</a>
{% for page in paginator.page_range %}
<a {% ifequal page_obj.number page %}class="active"{% else %}href="?page={{page}}"{% endifequal %}>{{page}}</a>
<a {% if page_obj.number == page %}class="active"{% else %}href="?page={{page}}"{% endif %}>{{page}}</a>
{% endfor %}
<a {% if page_obj.has_next %}

View File

@@ -1,6 +1,6 @@
""" the main URL config that imports many URL configs from the applications. """
from django.conf import settings
from django.conf.urls import include, url
from django.urls import include, path
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.sitemaps.views import sitemap
@@ -15,6 +15,7 @@ from maistar_ranking.sitemaps import *
from membership.views import MembershipDetail
admin.autodiscover()
# register_converter('path')
sitemaps = {
'event_rankings': EventRankingSitemap,
@@ -27,41 +28,33 @@ sitemaps = {
}
urlpatterns = [ # Ignore PyLintBear (C0103)
url(r'^$', views.StartPage.as_view()),
url(r'^404/$', TemplateView.as_view(template_name='404.html')),
url(r'^add_page/(?P<path>[\+\.\-\d\w\/]*)$',
views.PageAddForm.as_view(), name='add-page'),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', admin.site.urls),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
url(r'^comments/', include('django_comments.urls')),
url(r'^edit_page/(?P<path>[\+\.\-\d\w\/]*)$',
views.PageEditForm.as_view(), name='edit-page'),
url(r'^events/', include('events.urls')),
url(r'^events.ics$', EventListIcal.as_view(), name='events-ical'),
url(r'^feeds/latest/$', feeds.LatestNews(), name='feed-latest-news'),
url(r'^feeds/comments/$', feeds.LatestComments(),
name='feed-latest-comments'),
url(r'^gallery/', include('events.gallery_urls')),
url(r'^google25dabc1a49a9ef03.html$', TemplateView.as_view(
template_name='google25dabc1a49a9ef03.html')),
url(r'^i18n/', include('django.conf.urls.i18n'), name='start-page'),
url(r'^index.html$', views.StartPage.as_view()),
url(r'^manifest.json$',
TemplateView.as_view(template_name='manifest.json')),
url(r'^membership/', include('membership.urls')),
url(r'^news/', include('content.news_urls')),
url(r'^ranking/', include('mahjong_ranking.urls')),
url(r'^ranking/', include('maistar_ranking.urls')),
url(r'^sitemap\.xml$', sitemap, {
'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
url(r'^robots.txt$', TemplateView.as_view(template_name='robots.txt')),
url(r'^users/$', MembershipDetail.as_view(), name='membership-details'),
url(r'^users/(?P<username>[\-\.\d\w]+)/$',
MembershipDetail.as_view(), name='membership-details'),
url(r'^(?P<path>[\-\d\w\/]+)\.html$',
views.PageHtml.as_view(), name='view-page'),
url(r'^(?P<path>[\-\d\w\/]+)\.pdf$', views.PagePdf.as_view()),
path("", views.StartPage.as_view(), name="index"),
path('index.html', views.StartPage.as_view()),
path('404/', TemplateView.as_view(template_name='404.html'), name="404"),
path('admin/doc/', include('django.contrib.admindocs.urls'), name="django-docs"),
path('admin/', admin.site.urls, name="django-admin"),
path('ckeditor/', include('ckeditor_uploader.urls')),
path('comments/', include('django_comments.urls')),
path('events/', include('events.urls')),
path('events.ics', EventListIcal.as_view(), name='events-ical'),
path('feeds/latest/', feeds.LatestNews(), name='feed-latest-news'),
path('feeds/comments/', feeds.LatestComments(), name='feed-latest-comments'),
path('gallery/', include('events.gallery_urls')),
path('google25dabc1a49a9ef03.html', TemplateView.as_view(template_name='google25dabc1a49a9ef03.html')),
path('i18n/', include('django.conf.urls.i18n'), name='start-page'),
path('manifest.json', TemplateView.as_view(template_name='manifest.json')),
path('membership/', include('membership.urls')),
path('news/', include('content.news_urls')),
path('ranking/', include('mahjong_ranking.urls')),
path('ranking/', include('maistar_ranking.urls')),
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
path('robots.txt', TemplateView.as_view(template_name='robots.txt')),
path('users/', MembershipDetail.as_view(), name='membership-details'),
path('users/<slug:username>/', MembershipDetail.as_view(), name='membership-details'),
path('add_page/<path:path>', views.PageAddForm.as_view(), name='add-page'),
path('edit_page/<path:path>', views.PageEditForm.as_view(), name='edit-page'),
path('<path:path>.html', views.PageHtml.as_view(), name='view-page'),
path('<path:path>.pdf', views.PagePdf.as_view()),
]
if settings.DEBUG:
@@ -70,8 +63,8 @@ if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
if 'rosetta' in settings.INSTALLED_APPS:
urlpatterns += [url(r'^rosetta/', include('rosetta.urls'))]
urlpatterns += [path("rosetta/", include('rosetta.urls'))]
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls)), ]
urlpatterns += [path('__debug__/', include(debug_toolbar.urls)), ]

View File

@@ -1,6 +1,7 @@
"""
Helper to generate XLSX Spreadsheets in an uniform way.
"""
import datetime
from datetime import date
import openpyxl
@@ -68,6 +69,8 @@ def getattr_recursive(obj, attr_string):
for attr in attr_list:
return_value = getattr(obj, attr)
obj = return_value
if isinstance(return_value, datetime.datetime):
return_value = return_value.replace(tzinfo=None)
return return_value

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.mahjong_ranking\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-07-20 21:25+0200\n"
"PO-Revision-Date: 2018-05-08 00:20+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -19,15 +19,15 @@ msgstr ""
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.8.1\n"
#: admin.py:24
#: admin.py:26
msgid "Recalculate"
msgstr "Neuberechnen"
#: admin.py:34
#: admin.py:36
msgid "Confirm"
msgstr "Bestätigen"
#: admin.py:44
#: admin.py:46
msgid "Set unconfirmed"
msgstr "Als unbestätigt markieren"
@@ -35,7 +35,7 @@ msgstr "Als unbestätigt markieren"
msgid "start"
msgstr "Beginn"
#: models.py:91 templates/mahjong_ranking/player_dan_score.html:14
#: models.py:93 templates/mahjong_ranking/player_dan_score.html:14
#: templates/mahjong_ranking/player_invalid_score.html:13
#: templates/mahjong_ranking/player_kyu_score.html:15
#: templates/mahjong_ranking/player_ladder_score.html:15
@@ -43,16 +43,16 @@ msgstr "Beginn"
msgid "Start"
msgstr "Beginn"
#: models.py:92
#: models.py:94
msgid "This is crucial to get the right Hanchans that scores"
msgstr "Wichtig damit die richtigen Hanchans in die Wertung kommen."
#: models.py:99
#: models.py:101
msgid "Player 1"
msgstr "Spieler 1"
#: models.py:100 models.py:102 models.py:119 models.py:121 models.py:138
#: models.py:140 models.py:157 models.py:159
#: models.py:102 models.py:104 models.py:121 models.py:123 models.py:140
#: models.py:142 models.py:159 models.py:161
#: templates/mahjong_ranking/eventhanchan_list.html:19
#: templates/mahjong_ranking/eventranking_list.html:21
#: templates/mahjong_ranking/hanchan_confirm_delete.html:16
@@ -62,76 +62,76 @@ msgstr "Spieler 1"
msgid "Score"
msgstr "Punkte"
#: models.py:112 models.py:131 models.py:150 models.py:169 models.py:171
#: models.py:114 models.py:133 models.py:152 models.py:171 models.py:173
#: templates/mahjong_ranking/hanchan_form.html:20
#: templates/mahjong_ranking/player_dan_score.html:18
#: templates/mahjong_ranking/player_invalid_score.html:17
msgid "Comment"
msgstr "Kommentar"
#: models.py:118
#: models.py:120
msgid "Player 2"
msgstr "Spieler 2"
#: models.py:137
#: models.py:139
msgid "Player 3"
msgstr "Spieler 3"
#: models.py:156
#: models.py:158
msgid "Player 4"
msgstr "Spieler 4"
#: models.py:173
#: models.py:175
msgid "Has been Confirmed"
msgstr "Wurde bestätigt"
#: models.py:174
#: models.py:176
msgid "Only valid and confirmed Hanchans will be counted in the rating."
msgstr "Nur gültige und bestätigte Hanchans kommen in die Wertung."
#: models.py:179 models.py:607 templates/mahjong_ranking/ladder_redbox.html:29
#: models.py:181 models.py:620 templates/mahjong_ranking/ladder_redbox.html:29
#: templates/mahjong_ranking/player_ladder_score.html:63
msgid "Season"
msgstr "Saison"
#: models.py:184
#: models.py:186
msgid "Hanchan"
msgstr "Hanchan"
#: models.py:185 templates/mahjong_ranking/eventranking_list.html:17
#: models.py:187 templates/mahjong_ranking/eventranking_list.html:17
msgid "Hanchans"
msgstr "Hanchans"
#: models.py:188
#: models.py:190
msgid "Hanchan from {0:%Y-%m-%d} at {0:%H:%M} with {1}"
msgstr "Hanchan vom {0:%Y-%m-%d} um {0:%H:%M} mit {1}"
#: models.py:215
#: models.py:217
#, python-format
msgid "%s can't attend the same game multiple times"
msgstr "%s kann an einem Spiel nicht mehrfach teilnehmen."
#: models.py:223
#: models.py:225
msgid "Games in the future may not be added, Dr. Brown"
msgstr "Spiele aus der Zukunft dürfen noch nicht erfasst werden. Dr. Brown."
#: models.py:225
#: models.py:227
msgid "Only games during the event are allowed"
msgstr "Nur Spiele während der Veranstaltung zählen."
#: models.py:228
#: models.py:230
msgid "Gamescore is lower then 100.000 Pt."
msgstr "Spielstand ist weniger als 100.000 Punkte"
#: models.py:230
#: models.py:232
msgid "Gamescore is over 100.000 Pt."
msgstr "Spielstand ist über 100.000 Punkte."
#: models.py:362
#: models.py:368
msgid "Kyū/Dan Ranking"
msgstr "Kyū/Dan Wertung"
#: models.py:363
#: models.py:369
msgid "Kyū/Dan Rankings"
msgstr "Kyū/Dan Wertungen"
@@ -386,7 +386,7 @@ msgstr "%s wurde erfolgreich aktualisiert."
msgid "%s has been added successfully. You can now add a new one."
msgstr "%s wurde erfolgreich hinzugefügt. Du kannst eine neue eintragen."
#: views.py:219
#: views.py:218
msgid "No user found matching the name {}"
msgstr "Kein Benutzer mit dem Namen %s gefunden"

View File

@@ -0,0 +1,56 @@
"""
Recalculates all Kyu/Dan Rankings until the given date a writes them to the legacy fields.
"""
from django.core.management.base import BaseCommand
from datetime import datetime, date, time
from mahjong_ranking import models
from django.utils.dateparse import parse_date
from django.utils import timezone
LEGACY_ATTRIBUTES = (
"dan",
"dan_points",
"max_dan_points",
"kyu",
"kyu_points",
"hanchan_count",
"good_hanchans",
"won_hanchans"
)
class Command(BaseCommand):
""" Recalculates all Kyu/Dan Rankings until the given date a writes them to the legacy fields. """
help = "Recalculates all Kyu/Dan Rankings until the given date a writes them to the legacy fields."
def add_arguments(self, parser):
parser.add_argument('-s', '--since', nargs='?', type=parse_date,
metavar='YYYY-MM-DD',
help='Use all Hanchans since the given date.')
parser.add_argument('-u', '--until', nargs='?', type=parse_date,
metavar='YYYY-MM-DD',
help='Only use Hanchans until the given date.')
def handle(self, *args, **options):
since = options.get('since', None)
until = options.get('until', None)
if isinstance(since, date):
since = datetime.combine(since, time(0, 0, 0))
since = timezone.make_aware(since)
if isinstance(until, date):
until = datetime.combine(until, time(23, 59, 59))
until = timezone.make_aware(until)
models.KyuDanRanking.objects.update(since=since, until=until, force_recalc=True)
# write the updated values to the legacy fields
for ranking in models.KyuDanRanking.objects.all():
print(ranking)
for attribute in LEGACY_ATTRIBUTES:
setattr(ranking, f"legacy_{attribute}", getattr(ranking, attribute))
value = getattr(ranking, attribute)
legacy_value = getattr(ranking, f"legacy_{attribute}")
print(f"{attribute}: {value}, legacy_{attribute}: {legacy_value}")
ranking.legacy_date = until.date()
print(f"legacy_date: {ranking.legacy_date}")
ranking.save()

View File

@@ -11,7 +11,7 @@ from django.utils import timezone
class Command(BaseCommand):
""" Recalculate all Kyu/Dan Rankings """
""" reset every dan player to 1st dan with 0 points. """
help = "reset every dan player to 1st dan with 0 points."

View File

@@ -237,8 +237,9 @@ class KyuDanRankingManager(models.Manager):
def update(self, since=None, until=None, force_recalc=False):
old_attr = {'dan': None, 'dan_points': None,
'kyu': None, 'kyu_points': None, 'won_hanchans': None,
'good_hanchans': None, 'hanchan_count': None}
'kyu': None, 'kyu_points': None,
'won_hanchans': None, 'good_hanchans': None,
'hanchan_count': None}
for ranking in self.all():
old_attr = {attr: getattr(ranking, attr) for attr in
old_attr.keys()}

View File

@@ -14,6 +14,7 @@ from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext as _
from events.models import Event
from . import DAN_RANKS_DICT, LOGGER, set_dirty
from . import managers
@@ -349,6 +350,7 @@ class KyuDanRanking(models.Model):
legacy_date = models.DateField(blank=True, null=True)
legacy_dan = models.PositiveSmallIntegerField(blank=True, null=True)
legacy_dan_points = models.PositiveIntegerField(blank=True, null=True)
legacy_max_dan_points = models.PositiveIntegerField(default=0)
legacy_kyu = models.PositiveSmallIntegerField(blank=True, null=True)
legacy_kyu_points = models.PositiveIntegerField(blank=True, null=True)
legacy_hanchan_count = models.PositiveIntegerField(blank=True, null=True)
@@ -359,7 +361,10 @@ class KyuDanRanking(models.Model):
objects = managers.KyuDanRankingManager()
class Meta(object):
ordering = ('-dan_points', 'dan', '-kyu_points')
ordering = (models.F("dan").desc(nulls_last=True),
'-dan_points', '-kyu_points',
'-won_hanchans', '-good_hanchans',
'-last_hanchan_date')
verbose_name = _(u'Kyū/Dan Ranking')
verbose_name_plural = _(u'Kyū/Dan Rankings')
@@ -474,7 +479,7 @@ class KyuDanRanking(models.Model):
# Setze alles auf die legacy Werte und berechne alles von neuem.
self.dan = self.legacy_dan
self.dan_points = self.legacy_dan_points or 0
self.max_dan_points = self.dan_points
self.max_dan_points = self.legacy_max_dan_points or 0
self.kyu = self.legacy_kyu
self.kyu_points = self.legacy_kyu_points or 0
self.hanchan_count = self.legacy_hanchan_count or 0
@@ -491,19 +496,24 @@ class KyuDanRanking(models.Model):
since = timezone.make_aware(
datetime.combine(self.legacy_date, time(0, 0, 0))
)
LOGGER.info(
"recalculating Kyu/Dan points for %(user)s since %(since)s...",
{'user': self.user, 'since': str(since)}
)
if since:
valid_hanchans = valid_hanchans.filter(start__gt=since)
else:
since = valid_hanchans.aggregate(since=models.Min("start"))["since"]
if until:
valid_hanchans = valid_hanchans.filter(start__lte=until)
else:
until = valid_hanchans.aggregate(until=models.Max("start"))["until"]
if valid_hanchans.count() > 0:
LOGGER.info(f"recalculating Kyu/Dan points for {self.user} ({since:%Y-%m-%d} - {until:%Y-%m-%d})...")
else:
LOGGER.info(f"No new valid Hanchans for {self.user}...")
for hanchan in valid_hanchans:
self.hanchan_count += 1
LOGGER.info(f"{self.user} Hanchan no. {self.hanchan_count} from {hanchan.start}")
hanchan.get_playerdata(self.user)
if since and hanchan.start < since:
LOGGER.debug(hanchan, "<", since, "no recalc")
LOGGER.info(hanchan, "<", since, "no recalc")
self.dan_points += hanchan.dan_points or 0
self.kyu_points += hanchan.kyu_points or 0
self.update_rank()

View File

@@ -31,7 +31,7 @@
{% for season_link in season_list%}
<option
value="{% url 'mahjong-ladder' season_link %}"
{% ifequal season season_link %} selected="selected"{% endifequal %}>{{ season_link }}
{% if season == season_link %} selected="selected"{% endif %}>{{ season_link }}
</option>
{% endfor %}
</select>

View File

@@ -64,7 +64,7 @@
<select id="season" name="season" size="1">
{% for season_link in season_list%}
<option
{% ifequal season season_link %} selected="selected"{% endifequal %}
{% if season == season_link %} selected="selected"{% endif %}
value="{{ season_link }}">{{ season_link }}</option>
{% endfor %}
</select>

View File

@@ -1,38 +1,24 @@
""" URLS to display the Riichi Mahjong Rankings and the Ladder system."""
from django.conf.urls import url
from django.urls import path
from django.views.generic import RedirectView
from . import views
urlpatterns = [ # Ignore PyLintBear (C0103)
url(r'^$',
RedirectView.as_view(url='/ranking/mahjong-ladder/', permanent=True)),
url(r'^event/(?P<event>[\d]+)/add-hanchan/$',
views.HanchanForm.as_view(), name="add-hanchan-form"),
url(r'^event/(?P<event>[\d]+)/edit/$',
views.EventHanchanForm.as_view(), name="event-hanchan-form"),
url(r'^event/(?P<event>[\d]+)/mahjong/$',
views.EventHanchanList.as_view(), name="event-hanchan-list"),
url(r'^event/(?P<event>[\d]+)/mahjong-ranking/$',
views.EventRankingList.as_view(), name="event-ranking"),
url(r'^hanchan/(?P<hanchan>[\d]+)/edit/$',
views.HanchanForm.as_view(), name="edit-hanchan"),
url(r'^hanchan/(?P<hanchan>[\d]+)/delete/$',
views.DeleteHanchan.as_view(), name="delete-hanchan"),
url(r'^mahjong-ladder/$', views.SeasonRankingList.as_view(),
name="mahjong-ladder"),
url(r'^mahjong-ladder/(?P<season>[\d]+)/$',
views.SeasonRankingList.as_view(), name="mahjong-ladder"),
url(r'^player/(?P<username>[\-\.\d\w]+)/dan/$',
views.PlayerDanScore.as_view(), name="player-dan-score"),
url(r'^player/(?P<username>[\-\.\d\w]+)/invalid/$',
views.PlayerInvalidScore.as_view(), name="player-invalid-score"),
url(r'^player/(?P<username>[\-\.\d\w]+)/kyu/$',
views.PlayerKyuScore.as_view(), name="player-kyu-score"),
url(r'^player/(?P<username>[\-\.\d\w]+)/ladder/$',
views.PlayerLadderScore.as_view(), name="player-ladder-score"),
url(r'^mahjong/$', views.KyuDanRankingList.as_view(),
name="kyudanranking-list"),
url(r'^mahjong/(?P<order_by>[\+\-][a-z_]+)/$',
views.KyuDanRankingList.as_view(), name="kyudanranking-list"),
urlpatterns = [
path("", RedirectView.as_view(url='/ranking/mahjong-ladder/', permanent=True)),
path('event/<int:event>/add-hanchan/', views.HanchanForm.as_view(), name="add-hanchan-form"),
path('event/<int:event>/edit/', views.EventHanchanForm.as_view(), name="event-hanchan-form"),
path('event/<int:event>/mahjong/', views.EventHanchanList.as_view(), name="event-hanchan-list"),
path('event/<int:event>/mahjong-ranking/', views.EventRankingList.as_view(), name="event-ranking"),
path('hanchan/<int:hanchan>/edit/', views.HanchanForm.as_view(), name="edit-hanchan"),
path('hanchan/<int:hanchan>/delete/', views.DeleteHanchan.as_view(), name="delete-hanchan"),
path('mahjong-ladder/', views.SeasonRankingList.as_view(), name="mahjong-ladder"),
path('mahjong-ladder/<int:season>/', views.SeasonRankingList.as_view(), name="mahjong-ladder"),
path('player/<slug:username>/dan/', views.PlayerDanScore.as_view(), name="player-dan-score"),
path('player/<slug:username>/invalid/', views.PlayerInvalidScore.as_view(), name="player-invalid-score"),
path('player/<slug:username>/kyu/', views.PlayerKyuScore.as_view(), name="player-kyu-score"),
path('player/<slug:username>/ladder/', views.PlayerLadderScore.as_view(), name="player-ladder-score"),
path('mahjong/', views.KyuDanRankingList.as_view(), name="kyudanranking-list"),
path('mahjong/<str:order_by>/', views.KyuDanRankingList.as_view(), name="kyudanranking-list"),
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.mahjong_ranking\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-06-09 22:00+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -69,7 +69,7 @@ msgstr "Wurde bestätigt"
msgid "the game only counts whe it has been confirmed"
msgstr "das Spiel zählt nur wenn es bestätigt wurde"
#: models.py:70 models.py:153 templates/maistar_ranking/player_game_list.html:6
#: models.py:70 models.py:154 templates/maistar_ranking/player_game_list.html:6
#: templates/maistar_ranking/ranking_list.html:4
#: templates/maistar_ranking/ranking_list.html:72
msgid "Season"

View File

@@ -4,6 +4,6 @@
{% block additional_nav_elements %}
<a href="{% url 'season_ranking-archive' %}" class="{% if is_archive %}active{% endif %}">{% trans 'Archive' %}</a>
{% if perms.events.add_event %}
<a href="{% url 'event-form' %}" class="{% ifequal request.path '/events/add/' %}active{% endifequal %}">{% trans 'Add Event' %}</a>
<a href="{% url 'event-form' %}" class="{% if request.path == '/events/add/' %}active{% endif %}">{% trans 'Add Event' %}</a>
{% endif %}
{% endblock %}

View File

@@ -73,7 +73,7 @@
<select id="season" name="season" size="1" onChange="window.location.href = document.season_select.season.options[document.season_select.season.selectedIndex].value;">
{% for season_link in season_list%}
<option
{% ifequal season season_link %} selected="selected"{% endifequal %}
{% if season == season_link %} selected="selected"{% endif %}
value="{% url 'maistar-ranking' season=season_link %}" >{{ season_link }}</option>
{% endfor %}
</select>

View File

@@ -1,24 +1,16 @@
""" Definition of the URL paths to access the views of the Maistar ranking. """
from django.conf.urls import url
from django.urls import path
from . import views
urlpatterns = [
url('^$', views.ListRankings.as_view()),
url(r'^event/(?P<event>[\d]+)/maistar/$',
views.ListGames.as_view(), name="maistar-game-list"),
url(r'^event/(?P<event>[\d]+)/maistar/add/$',
views.GameForm.as_view(), name="maistar-add-game"),
url(r'^maistar/(?P<game>[\d]+)/edit/$',
views.GameForm.as_view(), name="maistar-edit-game"),
url(r'^maistar/(?P<game>[\d]+)/delete/$',
views.DeleteGame.as_view(), name="maistar-delete-game"),
url(r'^maistar/$',
views.ListRankings.as_view(), name="maistar-ranking"),
url(r'^maistar/(?P<season>[\d]+)/$',
views.ListRankings.as_view(), name="maistar-ranking"),
url(r'^player/(?P<username>[\-\.\d\w]+)/maistar/$',
views.ListPlayerGames.as_view(), name="maistar-player-games"),
url(r'^player/(?P<username>[\-\.\d\w]+)/maistar/(?P<season>[\d]+)/$',
views.ListPlayerGames.as_view(), name="maistar-player-games"),
path("", views.ListRankings.as_view()),
path('event/<int:event>/maistar/', views.ListGames.as_view(), name="maistar-game-list"),
path('event/<int:event>/maistar/add/$', views.GameForm.as_view(), name="maistar-add-game"),
path('maistar/', views.ListRankings.as_view(), name="maistar-ranking"),
path('maistar/<int:game>/edit/', views.GameForm.as_view(), name="maistar-edit-game"),
path('maistar/<int:game>/delete/', views.DeleteGame.as_view(), name="maistar-delete-game"),
path('maistar/<int:season>/', views.ListRankings.as_view(), name="maistar-ranking"),
path('player/<slug:username>/maistar/', views.ListPlayerGames.as_view(), name="maistar-player-games"),
path('player/<slug:username>/maistar/<int:season>/', views.ListPlayerGames.as_view(), name="maistar-player-games"),
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.membership\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-06-09 22:00+0200\n"
"PO-Revision-Date: 2018-05-08 00:19+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -35,38 +35,38 @@ msgstr "Ausgewählte Benutzer freischalten"
msgid "Cleanup selected Activation Requests"
msgstr "Ausgewählte Aktivierungsanfragen bereinigen"
#: admin.py:62
#: admin.py:65
#, python-format
msgid "Can't remove personal data from active member %s."
msgstr ""
"Persönliche Daten von aktiven Mitglied %s können nicht entfernt werden."
#: admin.py:64
#: admin.py:68
#, python-format
msgid "Cleared %d personal data profiles."
msgstr "Persönliche Daten in %d Profilen entfernt."
#: admin.py:66
#: admin.py:71
msgid "Clear personal Data"
msgstr "Persönliche Daten bereinigen"
#: admin.py:75
#: admin.py:80
msgid "Group"
msgstr "Gruppe"
#: admin.py:76
#: admin.py:81
msgid "Groups"
msgstr "Gruppen"
#: admin.py:102 forms.py:73 models.py:163 models.py:218
#: admin.py:107 forms.py:73 models.py:163 models.py:218
msgid "Membership"
msgstr "Mitgliedschaft"
#: admin.py:107
#: admin.py:112
msgid "Permissions"
msgstr "Berechtigung"
#: admin.py:109
#: admin.py:114
msgid "Important dates"
msgstr "Wichtige Daten"

View File

@@ -50,10 +50,10 @@
<li><strong>{% trans "Member Since" %}:</strong> {{membership.date_joined}}</li>
<li><strong>{% trans "Last Login" %}:</strong> {{membership.last_login}}</li>
</ul>
{% ifequal membership user %}
{% if membership == user %}
<a href="{% url 'membership-edit' membership.username %}" class="button"> <span class="fa fa-pencil"></span> {% trans "Edit Profile" %} </a>
<a href="{% url 'password_change' %}" class="button"> <span class="fa fa-key"></span> {% trans 'Change Password' %}</a>
{% endifequal %}
{% endif %}
</div>
{% endif %}

View File

@@ -4,38 +4,25 @@ Created on 03.10.2011
@author: christian
"""
import django.contrib.auth.views as auth_views
from django.conf.urls import url
from django.urls import path
from . import views
urlpatterns = [
url(r'^$', views.MembershipDetail.as_view()),
url(r'^activate/(?P<activation_key>[\d\w]+)/$',
views.ActivateRegistration.as_view(),
name='membership-activate-registration'),
url(r'^activation_sent/$',
views.ActivationSent.as_view(),
name="membership-registration-complete"),
url(r'^login/$', auth_views.LoginView.as_view(), name='login'),
url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'),
url(r'^password_change/$', auth_views.PasswordChangeView.as_view(),
name='password_change'),
url(r'^password_change/done/$', auth_views.PasswordChangeDoneView.as_view(),
name='password_change_done'),
url(r'^password_reset/$', auth_views.PasswordResetView.as_view(),
name='password_reset'),
url(r'^password_reset/done/$', auth_views.PasswordResetDoneView.as_view(),
name='password_reset_done'),
url(r'^register/$', views.RegisterForm.as_view(),
name="membership-register"),
url(
r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm'),
url(r'^reset/done/$', auth_views.PasswordResetCompleteView.as_view(),
name='password_reset_complete'),
url(r'^(?P<username>[\-\.\d\w]+)/$',
views.MembershipDetail.as_view(), name='membership-details'),
url(r'^(?P<username>[\-\.\d\w]+)/edit/$',
views.EditMembership.as_view(), name="membership-edit")
path("", views.MembershipDetail.as_view()),
path('activate/<str:activation_key>', views.ActivateRegistration.as_view(),
name='membership-activate-registration'),
path('activation_sent/', views.ActivationSent.as_view(), name="membership-registration-complete"),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('register/', views.RegisterForm.as_view(), name="membership-register"),
path('reset/<uuid:uidb64>/<str:token>/', auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm'),
path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
path('<slug:username>/', views.MembershipDetail.as_view(), name='membership-details'),
path('<slug:username>/edit/', views.EditMembership.as_view(), name="membership-edit")
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.utils\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-13 23:38+0100\n"
"POT-Creation-Date: 2023-06-09 22:00+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"Language-Team: Kasu <verein@kasu.at>\n"