From 400aa95005723913d36fa797a452995a14d1970d Mon Sep 17 00:00:00 2001 From: Xeniac Date: Wed, 10 May 2017 10:15:39 +0200 Subject: [PATCH] =?UTF-8?q?Anpassungen=20des=20Codes=20an=20Django=201.11?= =?UTF-8?q?=20mit=20Python=203=20Grapelli=20wurde=20entfernt,=20das=20neue?= =?UTF-8?q?=20Django=20Admin=20ist=20h=C3=BCbsch=20genug.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/events/gallery_urls.py | 7 ++- src/events/models.py | 6 +-- src/events/urls.py | 7 ++- src/kasu/settings.py | 15 +++--- src/kasu/urls.py | 18 +++---- src/mahjong_ranking/__init__.py | 9 ++-- src/mahjong_ranking/forms.py | 15 +++--- src/mahjong_ranking/middleware.py | 13 ++--- .../migrations/0004_auto_20170218_1947.py | 39 ++++++++++++++ src/mahjong_ranking/models.py | 52 ++++++++++++------- src/mahjong_ranking/urls.py | 10 ++-- src/mahjong_ranking/views.py | 1 - src/maistar_ranking/urls.py | 7 ++- src/manage.py | 2 +- src/membership/models.py | 4 +- .../templates/membership/register_form.html | 1 - .../membership/register_successful.html | 2 +- .../templates/registration/login.html | 5 +- src/membership/urls.py | 32 ++++++++---- src/utils/html5/base.py | 12 ++--- src/utils/html5/widgets.py | 8 +-- src/utils/html_cleaner.py | 13 ++--- src/utils/management/commands/compresscss.py | 8 +-- src/utils/management/commands/compressjs.py | 8 +-- src/utils/tests.py | 46 ++++++++++++++++ 25 files changed, 219 insertions(+), 121 deletions(-) create mode 100644 src/mahjong_ranking/migrations/0004_auto_20170218_1947.py create mode 100644 src/utils/tests.py diff --git a/src/events/gallery_urls.py b/src/events/gallery_urls.py index f681e53..3f2a1f0 100644 --- a/src/events/gallery_urls.py +++ b/src/events/gallery_urls.py @@ -1,10 +1,9 @@ # -*- encoding: utf-8 -*- -from django.conf.urls import patterns, url +from django.conf.urls import url from .views import * -urlpatterns = patterns( - '', +urlpatterns = [ url(r'^$', EventGallery.as_view(), name='event-gallery'), url(r'^(?P[\d]+)/$', EventPhotoList.as_view(), name='event-photo-list'), @@ -15,4 +14,4 @@ urlpatterns = patterns( url(r'^delete/(?P[\d]+)/$', DeleteEventPhoto.as_view(), name='delete-event-photo'), url(r'^upload/$', EventPhotoUpload.as_view(), name='event-photo-upload'), -) +] diff --git a/src/events/models.py b/src/events/models.py index 0f629e2..1f608e8 100644 --- a/src/events/models.py +++ b/src/events/models.py @@ -135,7 +135,7 @@ class Event(models.Model): verbose_name_plural = _('Events') ordering = ('start', 'end',) - def __unicode__(self): + def __str__(self): try: return "%(name)s (%(date)s)" % {'name': self.name, 'date': self.start.date()} @@ -235,7 +235,7 @@ class Location(models.Model): verbose_name = _('Venue') verbose_name_plural = _('Venues') - def __unicode__(self): + def __str__(self): return self.name @property @@ -306,7 +306,7 @@ class Photo(models.Model): verbose_name = _('Event Image') verbose_name_plural = _('Event Images') - def __unicode__(self): + def __str__(self): return os.path.basename(self.image.name) def rotate(self, rotate): diff --git a/src/events/urls.py b/src/events/urls.py index 4a965c1..ce7d34d 100644 --- a/src/events/urls.py +++ b/src/events/urls.py @@ -1,10 +1,9 @@ # -*- encoding: utf-8 -*- -from django.conf.urls import patterns, url +from django.conf.urls import url from django.views.generic import RedirectView from .views import * -urlpatterns = patterns( - '', +urlpatterns = [ url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)), url(r'^(?P[\d]{4})/$', EventArchiveYear.as_view(), name='event-archive'), @@ -19,4 +18,4 @@ urlpatterns = patterns( url(r'^add/$', EventForm.as_view(), name='event-form'), url(r'^archive/$', EventArchiveIndex.as_view(), name='event-archive'), url(r'^upcoming/$', UpcomingEvents.as_view(), name='upcoming-events'), -) +] diff --git a/src/kasu/settings.py b/src/kasu/settings.py index 490ebd9..4b708c5 100644 --- a/src/kasu/settings.py +++ b/src/kasu/settings.py @@ -29,7 +29,6 @@ STATICFILES_FINDERS = ( # Apps PREREQ_APPS = [ - 'grappelli', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -84,20 +83,20 @@ TEMPLATES = [ 'DIRS': [path.join(PROJECT_PATH, 'templates/')], 'OPTIONS': { 'context_processors': [ + 'content.context_processors.content_menus', 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.csrf', 'django.template.context_processors.debug', 'django.template.context_processors.i18n', 'django.template.context_processors.media', + 'django.template.context_processors.request', 'django.template.context_processors.static', 'django.template.context_processors.tz', 'django.contrib.messages.context_processors.messages', - 'django.core.context_processors.csrf', - 'django.core.context_processors.request', 'django.contrib.messages.context_processors.messages', - 'content.context_processors.content_menus', 'events.context_processors.upcoming_events', - 'social.apps.django_app.context_processors.backends', - 'social.apps.django_app.context_processors.login_redirect', +'social_django.context_processors.backends', + 'social_django.context_processors.login_redirect' ], 'loaders': [ ('django.template.loaders.cached.Loader', [ @@ -111,8 +110,8 @@ TEMPLATES = [ #Settings for Security Middleware CSP_DEFAULT_SRC = ("'self'",) -CSP_IMG_SRC = CSP_DEFAULT_SRC -CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'") +CSP_IMG_SRC = ("'self'", "'unsafe-eval'") +CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'", "'unsafe-eval'") CSP_STYLE_SRC = ("'self'", "'unsafe-inline'") SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True diff --git a/src/kasu/urls.py b/src/kasu/urls.py index 0fa8fd1..8c22bdb 100644 --- a/src/kasu/urls.py +++ b/src/kasu/urls.py @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- from django.conf import settings -from django.conf.urls import patterns, include, url +from django.conf.urls import include, url from django.contrib import admin from django.contrib.sitemaps.views import sitemap from django.views.generic.base import TemplateView @@ -20,8 +20,7 @@ sitemaps = { 'pages': PageSitemap, } -urlpatterns = patterns( - '', +urlpatterns = [ url(r'^$', StartPage.as_view()), url(r'^404/$', TemplateView.as_view(template_name='404.html')), url(r'^add_page/(?P[\+\.\-\d\w\/]+)/$', PageAddForm.as_view(), name='add-page'), @@ -37,7 +36,6 @@ urlpatterns = patterns( url(r'^feeds/comments/$', 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'^grappelli/', include('grappelli.urls')), url(r'^i18n/', include('django.conf.urls.i18n'), name='start-page'), url(r'^index.html$', StartPage.as_view()), url(r'^manifest.json$', TemplateView.as_view(template_name='manifest.json')), @@ -51,7 +49,8 @@ urlpatterns = patterns( url(r'^users/(?P[\-\.\d\w]+)/$', MembershipDetail.as_view(), name='membership-details'), url(r'^(?P[\-\d\w\/]+)\.html$', PageHtml.as_view(), name='view-page'), url(r'^(?P[\-\d\w\/]+)\.pdf$', PagePdf.as_view()), -) + url('', include('social_django.urls', namespace='social')) +] if settings.DEBUG: from django.conf.urls.static import static @@ -59,13 +58,8 @@ if settings.DEBUG: urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) if 'rosetta' in settings.INSTALLED_APPS: - urlpatterns += patterns('', url(r'^rosetta/', include('rosetta.urls')),) + urlpatterns += url(r'^rosetta/', include('rosetta.urls')) if 'debug_toolbar' in settings.INSTALLED_APPS: import debug_toolbar - urlpatterns += [ - url(r'^__debug__/', include(debug_toolbar.urls)), - ] - - - + urlpatterns.append(url(r'^__debug__/', include(debug_toolbar.urls))) \ No newline at end of file diff --git a/src/mahjong_ranking/__init__.py b/src/mahjong_ranking/__init__.py index 17267b9..3512947 100644 --- a/src/mahjong_ranking/__init__.py +++ b/src/mahjong_ranking/__init__.py @@ -1,7 +1,6 @@ # -*- encoding: utf-8 -*- -from django.utils.log import getLogger from django.core.cache import cache - +import logging KYU_RANKS = ( (45, 1), (40, 2), @@ -30,10 +29,10 @@ DAN_RANKS = ( DAN_RANKS_DICT = dict([(dan, points) for points, dan in DAN_RANKS]) MIN_HANCHANS_FOR_LADDER = 5 -logger = getLogger('kasu.mahjong_ranking') +logger = logging.getLogger('kasu.mahjong_ranking') -def set_dirty(event=None, season=None, user=None): +def set_dirty(event=None, season=None, user=None, hanchan_date=None): if season and user: key_to_add = (season, user) queue_name = 'ladder_ranking_queue' @@ -44,7 +43,7 @@ def set_dirty(event=None, season=None, user=None): key_to_add = (event, user) queue_name = 'event_ranking_queue' elif user: - key_to_add = user + key_to_add = (user, hanchan_date) queue_name = 'kyu_dan_ranking_queue' if key_to_add and queue_name: recalculation_queue = cache.get(queue_name, set()) diff --git a/src/mahjong_ranking/forms.py b/src/mahjong_ranking/forms.py index b6c70e9..8fb0efd 100644 --- a/src/mahjong_ranking/forms.py +++ b/src/mahjong_ranking/forms.py @@ -24,10 +24,10 @@ class HanchanForm(forms.ModelForm): class Meta(object): model = models.Hanchan fields = ('start', - 'player1', 'player1_input_score', # 'player1_comment', - 'player2', 'player2_input_score', # 'player2_comment', - 'player3', 'player3_input_score', # 'player3_comment', - 'player4', 'player4_input_score', # 'player4_comment', + 'player1', 'player1_input_score', + 'player2', 'player2_input_score', + 'player3', 'player3_input_score', + 'player4', 'player4_input_score', 'comment') widgets = {'event': forms.HiddenInput(), 'comment': forms.widgets.Textarea(attrs={'rows': 4, 'cols': 40}) @@ -35,11 +35,14 @@ class HanchanForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(HanchanForm, self).__init__(*args, **kwargs) - # self.fields['event'].widget.attrs['disabled'] = True - for i in xrange(1, 4): + player_queryset = USER_MODEL.objects.filter(is_active=True, + membership=True) + for i in range(1, 4): + player = 'player%d' % i player_input_score = 'player%d_input_score' % i self.fields[player_input_score].widget.attrs['size'] = 6 self.fields[player_input_score].widget.attrs['type'] = 'number' + self.fields[player].queryset = player_queryset diff --git a/src/mahjong_ranking/middleware.py b/src/mahjong_ranking/middleware.py index 7c87179..5333142 100644 --- a/src/mahjong_ranking/middleware.py +++ b/src/mahjong_ranking/middleware.py @@ -20,6 +20,9 @@ class DenormalizationUpdateMiddleware(object): def process_response(self, request, response): # We only do this in POST request, to speedup the responsetime. if request.method == 'POST': + print('event_ranking_queue', cache.get('event_ranking_queue', set())) + print('kyu_dan_ranking_queue', cache.get('kyu_dan_ranking_queue', set())) + print('ladder_ranking_queue', cache.get('ladder_ranking_queue', set())) queue = cache.get('event_ranking_queue', set()) if len(queue) > 0: self.recalculate_event_rankings(queue) @@ -45,8 +48,6 @@ class DenormalizationUpdateMiddleware(object): def recalculate_event_rankings(self, queue): # recalculate tournament (event) rankings: for event_id, user_id in queue: - logger.info("recalculate %d tournament Ranking in %s", - user_id, event_id) ranking = models.EventRanking.objects.get_or_create( event_id=event_id, user_id=user_id)[0] ranking.recalculate() @@ -54,10 +55,10 @@ class DenormalizationUpdateMiddleware(object): return queue def recalulate_kyu_dan_ranking(self, queue): - for user_id in queue: - ranking = models.KyuDanRanking.objects.get_or_create(user_id=user_id)[ - 0] - ranking.recalculate() + for user_id, hanchan_start in queue: + ranking = models.KyuDanRanking.objects.get_or_create( + user_id=user_id)[0] + ranking.recalculate(hanchan_start) return queue def recalculate_ladder_ranking(self, queue): diff --git a/src/mahjong_ranking/migrations/0004_auto_20170218_1947.py b/src/mahjong_ranking/migrations/0004_auto_20170218_1947.py new file mode 100644 index 0000000..15a3b23 --- /dev/null +++ b/src/mahjong_ranking/migrations/0004_auto_20170218_1947.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mahjong_ranking', '0003_auto_20160916_1800'), + ] + + operations = [ + migrations.AlterField( + model_name='hanchan', + name='comment', + field=models.TextField(verbose_name='Anmerkung', blank=True), + ), + migrations.AlterField( + model_name='hanchan', + name='player1_comment', + field=models.CharField(verbose_name='Anmerkung', max_length=255, editable=False, blank=True), + ), + migrations.AlterField( + model_name='hanchan', + name='player2_comment', + field=models.CharField(verbose_name='Anmerkung', max_length=255, editable=False, blank=True), + ), + migrations.AlterField( + model_name='hanchan', + name='player3_comment', + field=models.CharField(verbose_name='Anmerkung', max_length=255, editable=False, blank=True), + ), + migrations.AlterField( + model_name='hanchan', + name='player4_comment', + field=models.CharField(verbose_name='Anmerkung', max_length=255, editable=False, blank=True), + ), + ] diff --git a/src/mahjong_ranking/models.py b/src/mahjong_ranking/models.py index 39e2b25..02c8513 100644 --- a/src/mahjong_ranking/models.py +++ b/src/mahjong_ranking/models.py @@ -76,8 +76,7 @@ class EventRanking(models.Model): self.good_hanchans += 1 if hanchan.placement == 2 else 0 self.avg_placement = sum_placement / self.hanchan_count self.avg_score = sum_score / self.hanchan_count - self.save(force_update=True) - + self.save(force_update=True) class Hanchan(models.Model): @@ -95,7 +94,6 @@ class Hanchan(models.Model): player1 = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - limit_choices_to={'is_active': True, 'membership': True}, related_name='user_hanchan+', verbose_name=_('Player 1')) player1_input_score = models.IntegerField(_('Score')) @@ -115,7 +113,6 @@ class Hanchan(models.Model): player2 = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - limit_choices_to={'is_active': True, 'membership': True}, related_name='user_hanchan+', verbose_name=_('Player 2')) player2_input_score = models.IntegerField(_('Score')) @@ -135,7 +132,6 @@ class Hanchan(models.Model): player3 = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - limit_choices_to={'is_active': True, 'membership': True}, related_name='user_hanchan+', verbose_name=_('Player 3')) player3_input_score = models.IntegerField(_('Score')) @@ -155,7 +151,6 @@ class Hanchan(models.Model): player4 = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - limit_choices_to={'is_active': True, 'membership': True}, related_name='user_hanchan+', verbose_name=_('Player 4')) player4_input_score = models.IntegerField(_('Score')) @@ -205,11 +200,11 @@ class Hanchan(models.Model): try: self.clean_fields() - except ValidationError as e: - print e.update_error_dict(errors) + except ValidationError as exception: + exception.update_error_dict(errors) return - for i in xrange(1, 5): + for i in range(1, 5): player = getattr(self, 'player%d' % i) input_score = getattr(self, 'player%d_input_score' % i) score_sum += input_score @@ -309,7 +304,7 @@ class Hanchan(models.Model): @property def player_list(self): player_list = [] - for i in xrange(1, 5): + for i in range(1, 5): player_list.append({ 'user': getattr(self, 'player%d' % i), 'input_score': getattr(self, 'player%d_input_score' % i), @@ -324,10 +319,12 @@ class Hanchan(models.Model): return sorted(player_list, key=lambda player: player['input_score'], reverse=True) - def save(self, **kwargs): + def save(self, recalculate=True, **kwargs): self.season = self.event.mahjong_season or self.start.year self.full_clean() - self.compute_player_placements() + if recalculate: + self.compute_player_placements() + update_ranking(sender=Hanchan, instance=self) return models.Model.save(self, **kwargs) @@ -435,7 +432,7 @@ class KyuDanRanking(models.Model): else: return reverse('player-kyu-score', args=[self.user.username]) - def recalculate(self): + def recalculate(self, hanchan_start=None): """ Fetches all valid Hanchans from this Player and recalculates his Kyu/Dan Ranking. @@ -449,14 +446,23 @@ class KyuDanRanking(models.Model): self.good_hanchans = 0 self.won_hanchans = 0 - logger.info("recalculating Kyu/Dan points for %s...", self.user) + logger.info( + "recalculating Kyu/Dan points for %s since %s...", + self.user, str(hanchan_start) + ) self.update_rank() valid_hanchans = Hanchan.objects.confirmed_hanchans(user=self.user) valid_hanchans = valid_hanchans.order_by('start') if self.legacy_date: valid_hanchans = valid_hanchans.filter(start__gt=self.legacy_date) + """ TODO: Hanchan Punkte nur neu berechnen wenn sie vor hachan_start + lag. Es müssen aber alle durch die Schleife rennen, damit die Punkte + richtig gezählt werden.""" + if hanchan_start: + valid_hanchans = valid_hanchans.filter(start__gte=hanchan_start) self.hanchan_count += valid_hanchans.count() for hanchan in valid_hanchans: + logger.debug('Update Kyu/Dan points for Hanchan started on %s', str(hanchan.start)) hanchan.get_playerdata(self.user) hanchan.bonus_points = 0 hanchan.player_comment = u"" @@ -469,7 +475,7 @@ class KyuDanRanking(models.Model): self.won_hanchans += 1 if hanchan.placement == 1 else 0 self.good_hanchans += 1 if hanchan.placement == 2 else 0 hanchan.update_playerdata(self.user) - hanchan.save(force_update=True) + hanchan.save(recalculate=False) self.save(force_update=True) def update_hanchan_points(self, hanchan): @@ -537,7 +543,7 @@ class KyuDanRanking(models.Model): if self.dan_points > min_points: self.dan = dan_rank break - if self.dan > old_dan: + if old_dan == None or self.dan > old_dan: self.wins_in_a_row = 0 elif self.kyu_points < 1: self.kyu_points = 0 @@ -600,10 +606,16 @@ class SeasonRanking(models.Model): def update_ranking(sender, instance, **kwargs): for user in (instance.player1, instance.player2, instance.player3, instance.player4): - logger.debug("marking %s's kyu/dan for recalculation", user) - set_dirty(user=user.id) + logger.debug( + "marking %(user)s's kyu/dan for recalculation since %(start)s", + {'user':user, 'start':str(instance.start.date())} + ) + set_dirty(user=user.id, hanchan_date=instance.start.date()) if instance.season: - logger.debug("marking %s's ladder %i season for recalculation.", user, instance.season) + logger.debug( + "marking %s's ladder %i season for recalculation.", + user, instance.season + ) set_dirty(user=user.id, season=instance.season) logger.debug("marking season %d for recalculation.", instance.season) set_dirty(season=instance.season) @@ -611,4 +623,4 @@ def update_ranking(sender, instance, **kwargs): set_dirty(event=instance.event_id, user=user.id) models.signals.pre_delete.connect(update_ranking, sender=Hanchan) -models.signals.post_save.connect(update_ranking, sender=Hanchan) +# models.signals.post_save.connect(update_ranking, sender=Hanchan) diff --git a/src/mahjong_ranking/urls.py b/src/mahjong_ranking/urls.py index 85e6e1f..0c91581 100644 --- a/src/mahjong_ranking/urls.py +++ b/src/mahjong_ranking/urls.py @@ -5,14 +5,12 @@ Created on 03.10.2011 @author: christian """ -from django.conf.urls import * # @UnusedWildImport from django.views.generic import RedirectView - -import views +from django.conf.urls import url +from . import views -urlpatterns = patterns( - '', +urlpatterns = [ url(r'^$', RedirectView.as_view( url='/ranking/mahjong-ladder/', permanent=True) ), @@ -42,4 +40,4 @@ urlpatterns = patterns( name="kyudanranking-list"), url(r'^mahjong/(?P[\+\-\w]+)/$', views.KyuDanRankingList.as_view(), name="kyudanranking-list"), -) +] diff --git a/src/mahjong_ranking/views.py b/src/mahjong_ranking/views.py index c665a31..65df8e4 100644 --- a/src/mahjong_ranking/views.py +++ b/src/mahjong_ranking/views.py @@ -256,5 +256,4 @@ class PlayerLadderScore(PlayerScore): self.season = date.today().year hanchan_list = models.Hanchan.objects.season_hanchans( user=self.user, season=self.season) - print hanchan_list return hanchan_list diff --git a/src/maistar_ranking/urls.py b/src/maistar_ranking/urls.py index efe061e..2af9949 100644 --- a/src/maistar_ranking/urls.py +++ b/src/maistar_ranking/urls.py @@ -4,14 +4,13 @@ Created on 03.10.2011 @author: christian """ -from django.conf.urls import * # @UnusedWildImport +from django.conf.urls import url from django.views.generic import RedirectView from .views import DeleteGame, ListGames, ListPlayerGames, \ ListRankings, GameForm -urlpatterns = patterns( - 'maistar_ranking.views', +urlpatterns = [ url('^$', ListRankings.as_view()), url(r'^event/(?P[\d]+)/maistar/$', ListGames.as_view(), name="maistar-game-list"), @@ -28,4 +27,4 @@ urlpatterns = patterns( ListPlayerGames.as_view(), name="maistar-player-games"), url(r'^player/(?P[\-\.\d\w]+)/maistar/(?P[\d]+)/$', ListPlayerGames.as_view(), name="maistar-player-games"), -) +] diff --git a/src/manage.py b/src/manage.py index 1d37998..ccc0e52 100755 --- a/src/manage.py +++ b/src/manage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- encoding: utf-8 -*- import os diff --git a/src/membership/models.py b/src/membership/models.py index 4dc27f5..25722a6 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -96,7 +96,7 @@ class ActivationRequest(models.Model): verbose_name = _('pending activation') verbose_name_plural = _('pending activations') - def __unicode__(self): + def __str__(self): return _("user registration for %s") % self.user def activate(self): @@ -215,7 +215,7 @@ class Membership(AbstractUser): verbose_name = _('Membership') verbose_name_plural = _('Memberships') - def __unicode__(self): + def __str__(self): return self.username def get_absolute_url(self): diff --git a/src/membership/templates/membership/register_form.html b/src/membership/templates/membership/register_form.html index 6d564e1..8a34645 100644 --- a/src/membership/templates/membership/register_form.html +++ b/src/membership/templates/membership/register_form.html @@ -1,6 +1,5 @@ {% extends "base.html" %} {% load i18n fieldset_extras %} -{% load url from future %} {% block title %}{% trans "Registration"%}{% endblock %} {% block teaser%} diff --git a/src/membership/templates/membership/register_successful.html b/src/membership/templates/membership/register_successful.html index 421a4f3..86cd03b 100644 --- a/src/membership/templates/membership/register_successful.html +++ b/src/membership/templates/membership/register_successful.html @@ -1,6 +1,6 @@ {% extends "base.html" %} {% load i18n %} -{% load url from future %} + {% block title %}{% trans "Activation sent"%}{% endblock %} diff --git a/src/membership/templates/registration/login.html b/src/membership/templates/registration/login.html index fd532c7..47f3904 100755 --- a/src/membership/templates/registration/login.html +++ b/src/membership/templates/registration/login.html @@ -1,17 +1,16 @@ {% extends "base.html" %} {% load i18n %} -{% load url from future %} {% block title %}{% trans 'Login' %}{% endblock %} {% block description %}Anmelden auf Kasu.at{% endblock %} {% block extra_head %} - + {% endblock %} {% block teaser %}

{% trans 'Login' %}

{% endblock %} {% block maincontent %} -
+

Auf der Seite Anmelden

diff --git a/src/membership/urls.py b/src/membership/urls.py index cb4dcb9..f46ea6f 100644 --- a/src/membership/urls.py +++ b/src/membership/urls.py @@ -3,26 +3,38 @@ Created on 03.10.2011 @author: christian """ -from django.conf.urls import * # @UnusedWildImport +import django.contrib.auth.views as auth_views +from django.conf.urls import url, include from . import views - -urlpatterns = patterns( - '', - url('', include('social_django.urls', namespace='social')), - url('', include('django.contrib.auth.urls')), - url(r'^register/$', - views.RegisterForm.as_view(), - name="membership-register"), +urlpatterns = [ url(r'^activate/(?P[\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[0-9A-Za-z_\-]+)/(?P[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[\-\.\d\w]+)/$', views.MembershipDetail.as_view(), name='membership-details'), url(r'^(?P[\-\.\d\w]+)/edit/$', views.EditMembership.as_view(), name="membership-edit") -) +] diff --git a/src/utils/html5/base.py b/src/utils/html5/base.py index 773080f..e58b4e4 100644 --- a/src/utils/html5/base.py +++ b/src/utils/html5/base.py @@ -3,7 +3,7 @@ import re from django.core.urlresolvers import reverse from django.core.serializers.json import DjangoJSONEncoder from django.http import HttpResponse -from django.utils.encoding import smart_unicode, force_unicode +from django.utils.encoding import smart_text, force_text try: @@ -29,13 +29,13 @@ class LookupBase(object): return [] def get_item_label(self, item): - return smart_unicode(item) + return smart_text(item) def get_item_id(self, item): - return smart_unicode(item) + return smart_text(item) def get_item_value(self, item): - return smart_unicode(item) + return smart_text(item) def get_item(self, value): return value @@ -84,7 +84,7 @@ class LookupRegistry(object): def register(self, lookup): self.validate(lookup) - name = force_unicode(lookup.name()) + name = force_text(lookup.name()) if name in self._registry: raise LookupAlreadyRegistered(u'The name %s is already registered' % name) @@ -92,7 +92,7 @@ class LookupRegistry(object): def unregister(self, lookup): self.validate(lookup) - name = force_unicode(lookup.name()) + name = force_text(lookup.name()) if name not in self._registry: raise LookupNotRegistered(u'The name %s is not registered' % name) del self._registry[name] diff --git a/src/utils/html5/widgets.py b/src/utils/html5/widgets.py index 5dd04fc..6a4c31a 100644 --- a/src/utils/html5/widgets.py +++ b/src/utils/html5/widgets.py @@ -7,7 +7,7 @@ from django.conf import settings from django.forms import widgets from django.forms.utils import flatatt from django.utils import formats -from django.utils.encoding import force_unicode, force_text +from django.utils.encoding import force_text from django.utils.html import conditional_escape from django.utils.http import urlencode from django.utils.safestring import mark_safe @@ -98,7 +98,7 @@ class CheckboxInput(widgets.CheckboxInput): if not ( value is True or value is False or value is None or value == ''): # @IgnorePep8 # Only add the 'value' attribute if a value is non-empty. - final_attrs['value'] = force_unicode(value) + final_attrs['value'] = force_text(value) return mark_safe(u' %s' % (flatatt(final_attrs), title)) @@ -161,7 +161,7 @@ class Textarea(widgets.Widget): final_attrs = self.build_attrs(attrs, name=name) return mark_safe(u'%s' % (flatatt(final_attrs), conditional_escape( - force_unicode( + force_text( value)))) @@ -208,7 +208,7 @@ class LookupMultipleHiddenInput(widgets.MultipleHiddenInput): if model and isinstance(v, model): item = v v = lookup.get_item_id(item) - input_attrs = dict(value=force_unicode(v), **final_attrs) + input_attrs = dict(value=force_text(v), **final_attrs) if id_: # An ID attribute was given. Add a numeric index as a suffix # so that the inputs don't all have the same ID attribute. diff --git a/src/utils/html_cleaner.py b/src/utils/html_cleaner.py index 0cedce7..54785a3 100644 --- a/src/utils/html_cleaner.py +++ b/src/utils/html_cleaner.py @@ -3,7 +3,8 @@ Created on 19.10.2011 @author: christian """ -from BeautifulSoup import BeautifulSoup +from bs4 import BeautifulSoup +#TODO: Nach BeatutifulSoup 4 convertieren class HtmlCleaner(object): @@ -38,7 +39,7 @@ class HtmlCleaner(object): tag_removed = False def clean_attributes(self, tag): - for attr in tag._getAttrMap().keys(): + for attr in list(tag.attrs.keys()): if attr not in self.ACCEPTABELE_ATTRIBUTES: del tag[attr] elif tag[attr].count('script:'): @@ -57,14 +58,14 @@ class HtmlCleaner(object): @param fragment: """ while True: - soup = BeautifulSoup(fragment) + soup = BeautifulSoup(fragment, "html.parser") self.tag_removed = False self.counter += 1 - for tag in soup.findAll(True): + for tag in soup.find_all(True): self.clean_tag(tag) - fragment = unicode(soup) + fragment = str(soup) if self.tag_removed: continue else: break - return fragment + return fragment.strip() diff --git a/src/utils/management/commands/compresscss.py b/src/utils/management/commands/compresscss.py index ea3e6a9..6c6b4c7 100644 --- a/src/utils/management/commands/compresscss.py +++ b/src/utils/management/commands/compresscss.py @@ -219,9 +219,9 @@ class Command(BaseCommand): css_output = '%s/%s.css' % (CSS_ROOT, site.domain.replace('.', '_')) - print _("Compressing CSS for %s") % site.name - print "Input Dir: %s" % css_input - print "Output File: %s" % css_output + print("Compressing CSS for {}".format(site.name)) + print("Input Dir: {}".format(css_input)) + print("Output File: {}".format(css_output)) try: os.makedirs(css_input) @@ -232,7 +232,7 @@ class Command(BaseCommand): and append their content""" for file_name in fnmatch.filter(sorted(os.listdir(css_input)), '*.css'): - print ' Adding: %s' % file_name + print('Adding: {}'.format(file_name)) with open(os.path.join(css_input, file_name), 'r') as css_file: css += css_file.read() with open(css_output, 'w') as css_file: diff --git a/src/utils/management/commands/compressjs.py b/src/utils/management/commands/compressjs.py index dee10b4..9382c69 100644 --- a/src/utils/management/commands/compressjs.py +++ b/src/utils/management/commands/compressjs.py @@ -26,9 +26,9 @@ class Command(BaseCommand): js_input = os.path.join(JS_ROOT, site.domain) js_output = '%s/%s.js' % (JS_ROOT, site.domain.replace('.', '_')) - print _("Compressing JavaScript for %s") % site.name - print "Input Dir: %s" % js_input - print "Output File: %s" % js_output + print("Compressing JavaScript for {}".format(site.name)) + print("Input Dir: {}".format(js_input)) + print("Output File: %s".format(js_output)) try: os.makedirs(js_input) @@ -39,7 +39,7 @@ class Command(BaseCommand): # content js_files = fnmatch.filter(sorted(os.listdir(js_input)), '*.js') for file_name in js_files: - print " Adding: %s..." % file_name + print(" Adding: {}...".format(file_name)) input_file_name = os.path.join(js_input, file_name) with open(input_file_name, 'r') as input_file: output += input_file.read() diff --git a/src/utils/tests.py b/src/utils/tests.py new file mode 100644 index 0000000..bfb7515 --- /dev/null +++ b/src/utils/tests.py @@ -0,0 +1,46 @@ +import unittest +import html_cleaner + + +class HtmlTestCase(unittest.TestCase): + known_html = ( + ('Fett!', 'Fett!'), + ('Bad Link', 'Bad Link'), + (''' + + + + + + +
Hey Brad;
+
 
+
1) From your FAQ page at Webalizer.com the README + file link in question 19 to ftp://ftp.mrunix.net/pub/webalizer/README brings + a 404 Page Not Found error message.
+
 
+
2) My host recently + added Webalizer and I am trying to find the best way to keep the program running + correctly and to deny outsiders the ability to look at it. I would prefer not to + give others access to my stats.  I do web design and at any given time have + client demos in various stages of completion and other things I'd prefer not to + have the general public see popping up in my stats.  Does Webalizer have a + password protection mode or anything?
+
 
+
XXXXXX XXXXXXX
XXXXXXXXX Web Design
http://www.xxxxxxxxxxxx.com
(xxx) + xxx-xxxx
+ ''', + '' + ) + ) + + def test_html_cleaner(self): + """Ugly HTML Code has been made tidy""" + cleaner = html_cleaner.HtmlCleaner() + for original, tidy in self.known_html: + self.assertEqual(cleaner.clean_html(original), tidy) + +if __name__ == '__main__': + unittest.main()