Anpassungen des Codes an Django 1.11 mit Python 3
Grapelli wurde entfernt, das neue Django Admin ist hübsch genug.
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .views import *
|
from .views import *
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
url(r'^$', EventGallery.as_view(), name='event-gallery'),
|
url(r'^$', EventGallery.as_view(), name='event-gallery'),
|
||||||
url(r'^(?P<event>[\d]+)/$', EventPhotoList.as_view(),
|
url(r'^(?P<event>[\d]+)/$', EventPhotoList.as_view(),
|
||||||
name='event-photo-list'),
|
name='event-photo-list'),
|
||||||
@@ -15,4 +14,4 @@ urlpatterns = patterns(
|
|||||||
url(r'^delete/(?P<pk>[\d]+)/$', DeleteEventPhoto.as_view(),
|
url(r'^delete/(?P<pk>[\d]+)/$', DeleteEventPhoto.as_view(),
|
||||||
name='delete-event-photo'),
|
name='delete-event-photo'),
|
||||||
url(r'^upload/$', EventPhotoUpload.as_view(), name='event-photo-upload'),
|
url(r'^upload/$', EventPhotoUpload.as_view(), name='event-photo-upload'),
|
||||||
)
|
]
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class Event(models.Model):
|
|||||||
verbose_name_plural = _('Events')
|
verbose_name_plural = _('Events')
|
||||||
ordering = ('start', 'end',)
|
ordering = ('start', 'end',)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
try:
|
try:
|
||||||
return "%(name)s (%(date)s)" % {'name': self.name,
|
return "%(name)s (%(date)s)" % {'name': self.name,
|
||||||
'date': self.start.date()}
|
'date': self.start.date()}
|
||||||
@@ -235,7 +235,7 @@ class Location(models.Model):
|
|||||||
verbose_name = _('Venue')
|
verbose_name = _('Venue')
|
||||||
verbose_name_plural = _('Venues')
|
verbose_name_plural = _('Venues')
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -306,7 +306,7 @@ class Photo(models.Model):
|
|||||||
verbose_name = _('Event Image')
|
verbose_name = _('Event Image')
|
||||||
verbose_name_plural = _('Event Images')
|
verbose_name_plural = _('Event Images')
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
return os.path.basename(self.image.name)
|
return os.path.basename(self.image.name)
|
||||||
|
|
||||||
def rotate(self, rotate):
|
def rotate(self, rotate):
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import url
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
from .views import *
|
from .views import *
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)),
|
url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)),
|
||||||
url(r'^(?P<year>[\d]{4})/$', EventArchiveYear.as_view(),
|
url(r'^(?P<year>[\d]{4})/$', EventArchiveYear.as_view(),
|
||||||
name='event-archive'),
|
name='event-archive'),
|
||||||
@@ -19,4 +18,4 @@ urlpatterns = patterns(
|
|||||||
url(r'^add/$', EventForm.as_view(), name='event-form'),
|
url(r'^add/$', EventForm.as_view(), name='event-form'),
|
||||||
url(r'^archive/$', EventArchiveIndex.as_view(), name='event-archive'),
|
url(r'^archive/$', EventArchiveIndex.as_view(), name='event-archive'),
|
||||||
url(r'^upcoming/$', UpcomingEvents.as_view(), name='upcoming-events'),
|
url(r'^upcoming/$', UpcomingEvents.as_view(), name='upcoming-events'),
|
||||||
)
|
]
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ STATICFILES_FINDERS = (
|
|||||||
|
|
||||||
# Apps
|
# Apps
|
||||||
PREREQ_APPS = [
|
PREREQ_APPS = [
|
||||||
'grappelli',
|
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
@@ -84,20 +83,20 @@ TEMPLATES = [
|
|||||||
'DIRS': [path.join(PROJECT_PATH, 'templates/')],
|
'DIRS': [path.join(PROJECT_PATH, 'templates/')],
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
|
'content.context_processors.content_menus',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.template.context_processors.csrf',
|
||||||
'django.template.context_processors.debug',
|
'django.template.context_processors.debug',
|
||||||
'django.template.context_processors.i18n',
|
'django.template.context_processors.i18n',
|
||||||
'django.template.context_processors.media',
|
'django.template.context_processors.media',
|
||||||
|
'django.template.context_processors.request',
|
||||||
'django.template.context_processors.static',
|
'django.template.context_processors.static',
|
||||||
'django.template.context_processors.tz',
|
'django.template.context_processors.tz',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
'django.core.context_processors.csrf',
|
|
||||||
'django.core.context_processors.request',
|
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
'content.context_processors.content_menus',
|
|
||||||
'events.context_processors.upcoming_events',
|
'events.context_processors.upcoming_events',
|
||||||
'social.apps.django_app.context_processors.backends',
|
'social_django.context_processors.backends',
|
||||||
'social.apps.django_app.context_processors.login_redirect',
|
'social_django.context_processors.login_redirect'
|
||||||
],
|
],
|
||||||
'loaders': [
|
'loaders': [
|
||||||
('django.template.loaders.cached.Loader', [
|
('django.template.loaders.cached.Loader', [
|
||||||
@@ -111,8 +110,8 @@ TEMPLATES = [
|
|||||||
|
|
||||||
#Settings for Security Middleware
|
#Settings for Security Middleware
|
||||||
CSP_DEFAULT_SRC = ("'self'",)
|
CSP_DEFAULT_SRC = ("'self'",)
|
||||||
CSP_IMG_SRC = CSP_DEFAULT_SRC
|
CSP_IMG_SRC = ("'self'", "'unsafe-eval'")
|
||||||
CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'")
|
CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'", "'unsafe-eval'")
|
||||||
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
|
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
|
||||||
SECURE_BROWSER_XSS_FILTER = True
|
SECURE_BROWSER_XSS_FILTER = True
|
||||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
from django.conf import settings
|
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 import admin
|
||||||
from django.contrib.sitemaps.views import sitemap
|
from django.contrib.sitemaps.views import sitemap
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
@@ -20,8 +20,7 @@ sitemaps = {
|
|||||||
'pages': PageSitemap,
|
'pages': PageSitemap,
|
||||||
}
|
}
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
url(r'^$', StartPage.as_view()),
|
url(r'^$', StartPage.as_view()),
|
||||||
url(r'^404/$', TemplateView.as_view(template_name='404.html')),
|
url(r'^404/$', TemplateView.as_view(template_name='404.html')),
|
||||||
url(r'^add_page/(?P<path>[\+\.\-\d\w\/]+)/$', PageAddForm.as_view(), name='add-page'),
|
url(r'^add_page/(?P<path>[\+\.\-\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'^feeds/comments/$', LatestComments(), name='feed-latest-comments'),
|
||||||
url(r'^gallery/', include('events.gallery_urls')),
|
url(r'^gallery/', include('events.gallery_urls')),
|
||||||
url(r'^google25dabc1a49a9ef03.html$', TemplateView.as_view(template_name='google25dabc1a49a9ef03.html')),
|
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'^i18n/', include('django.conf.urls.i18n'), name='start-page'),
|
||||||
url(r'^index.html$', StartPage.as_view()),
|
url(r'^index.html$', StartPage.as_view()),
|
||||||
url(r'^manifest.json$', TemplateView.as_view(template_name='manifest.json')),
|
url(r'^manifest.json$', TemplateView.as_view(template_name='manifest.json')),
|
||||||
@@ -51,7 +49,8 @@ urlpatterns = patterns(
|
|||||||
url(r'^users/(?P<username>[\-\.\d\w]+)/$', 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$', PageHtml.as_view(), name='view-page'),
|
url(r'^(?P<path>[\-\d\w\/]+)\.html$', PageHtml.as_view(), name='view-page'),
|
||||||
url(r'^(?P<path>[\-\d\w\/]+)\.pdf$', PagePdf.as_view()),
|
url(r'^(?P<path>[\-\d\w\/]+)\.pdf$', PagePdf.as_view()),
|
||||||
)
|
url('', include('social_django.urls', namespace='social'))
|
||||||
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
@@ -59,13 +58,8 @@ if settings.DEBUG:
|
|||||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|
||||||
if 'rosetta' in settings.INSTALLED_APPS:
|
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:
|
if 'debug_toolbar' in settings.INSTALLED_APPS:
|
||||||
import debug_toolbar
|
import debug_toolbar
|
||||||
urlpatterns += [
|
urlpatterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))
|
||||||
url(r'^__debug__/', include(debug_toolbar.urls)),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
from django.utils.log import getLogger
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
import logging
|
||||||
KYU_RANKS = (
|
KYU_RANKS = (
|
||||||
(45, 1),
|
(45, 1),
|
||||||
(40, 2),
|
(40, 2),
|
||||||
@@ -30,10 +29,10 @@ DAN_RANKS = (
|
|||||||
DAN_RANKS_DICT = dict([(dan, points) for points, dan in DAN_RANKS])
|
DAN_RANKS_DICT = dict([(dan, points) for points, dan in DAN_RANKS])
|
||||||
MIN_HANCHANS_FOR_LADDER = 5
|
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:
|
if season and user:
|
||||||
key_to_add = (season, user)
|
key_to_add = (season, user)
|
||||||
queue_name = 'ladder_ranking_queue'
|
queue_name = 'ladder_ranking_queue'
|
||||||
@@ -44,7 +43,7 @@ def set_dirty(event=None, season=None, user=None):
|
|||||||
key_to_add = (event, user)
|
key_to_add = (event, user)
|
||||||
queue_name = 'event_ranking_queue'
|
queue_name = 'event_ranking_queue'
|
||||||
elif user:
|
elif user:
|
||||||
key_to_add = user
|
key_to_add = (user, hanchan_date)
|
||||||
queue_name = 'kyu_dan_ranking_queue'
|
queue_name = 'kyu_dan_ranking_queue'
|
||||||
if key_to_add and queue_name:
|
if key_to_add and queue_name:
|
||||||
recalculation_queue = cache.get(queue_name, set())
|
recalculation_queue = cache.get(queue_name, set())
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ class HanchanForm(forms.ModelForm):
|
|||||||
class Meta(object):
|
class Meta(object):
|
||||||
model = models.Hanchan
|
model = models.Hanchan
|
||||||
fields = ('start',
|
fields = ('start',
|
||||||
'player1', 'player1_input_score', # 'player1_comment',
|
'player1', 'player1_input_score',
|
||||||
'player2', 'player2_input_score', # 'player2_comment',
|
'player2', 'player2_input_score',
|
||||||
'player3', 'player3_input_score', # 'player3_comment',
|
'player3', 'player3_input_score',
|
||||||
'player4', 'player4_input_score', # 'player4_comment',
|
'player4', 'player4_input_score',
|
||||||
'comment')
|
'comment')
|
||||||
widgets = {'event': forms.HiddenInput(),
|
widgets = {'event': forms.HiddenInput(),
|
||||||
'comment': forms.widgets.Textarea(attrs={'rows': 4, 'cols': 40})
|
'comment': forms.widgets.Textarea(attrs={'rows': 4, 'cols': 40})
|
||||||
@@ -35,11 +35,14 @@ class HanchanForm(forms.ModelForm):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(HanchanForm, self).__init__(*args, **kwargs)
|
super(HanchanForm, self).__init__(*args, **kwargs)
|
||||||
# self.fields['event'].widget.attrs['disabled'] = True
|
player_queryset = USER_MODEL.objects.filter(is_active=True,
|
||||||
for i in xrange(1, 4):
|
membership=True)
|
||||||
|
for i in range(1, 4):
|
||||||
|
player = 'player%d' % i
|
||||||
player_input_score = 'player%d_input_score' % 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['size'] = 6
|
||||||
self.fields[player_input_score].widget.attrs['type'] = 'number'
|
self.fields[player_input_score].widget.attrs['type'] = 'number'
|
||||||
|
self.fields[player].queryset = player_queryset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ class DenormalizationUpdateMiddleware(object):
|
|||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
# We only do this in POST request, to speedup the responsetime.
|
# We only do this in POST request, to speedup the responsetime.
|
||||||
if request.method == 'POST':
|
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())
|
queue = cache.get('event_ranking_queue', set())
|
||||||
if len(queue) > 0:
|
if len(queue) > 0:
|
||||||
self.recalculate_event_rankings(queue)
|
self.recalculate_event_rankings(queue)
|
||||||
@@ -45,8 +48,6 @@ class DenormalizationUpdateMiddleware(object):
|
|||||||
def recalculate_event_rankings(self, queue):
|
def recalculate_event_rankings(self, queue):
|
||||||
# recalculate tournament (event) rankings:
|
# recalculate tournament (event) rankings:
|
||||||
for event_id, user_id in queue:
|
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(
|
ranking = models.EventRanking.objects.get_or_create(
|
||||||
event_id=event_id, user_id=user_id)[0]
|
event_id=event_id, user_id=user_id)[0]
|
||||||
ranking.recalculate()
|
ranking.recalculate()
|
||||||
@@ -54,10 +55,10 @@ class DenormalizationUpdateMiddleware(object):
|
|||||||
return queue
|
return queue
|
||||||
|
|
||||||
def recalulate_kyu_dan_ranking(self, queue):
|
def recalulate_kyu_dan_ranking(self, queue):
|
||||||
for user_id in queue:
|
for user_id, hanchan_start in queue:
|
||||||
ranking = models.KyuDanRanking.objects.get_or_create(user_id=user_id)[
|
ranking = models.KyuDanRanking.objects.get_or_create(
|
||||||
0]
|
user_id=user_id)[0]
|
||||||
ranking.recalculate()
|
ranking.recalculate(hanchan_start)
|
||||||
return queue
|
return queue
|
||||||
|
|
||||||
def recalculate_ladder_ranking(self, queue):
|
def recalculate_ladder_ranking(self, queue):
|
||||||
|
|||||||
39
src/mahjong_ranking/migrations/0004_auto_20170218_1947.py
Normal file
39
src/mahjong_ranking/migrations/0004_auto_20170218_1947.py
Normal file
@@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -79,7 +79,6 @@ class EventRanking(models.Model):
|
|||||||
self.save(force_update=True)
|
self.save(force_update=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Hanchan(models.Model):
|
class Hanchan(models.Model):
|
||||||
"""
|
"""
|
||||||
Ein komplette Runde Mahjong, die aus genau 4 Spielern bestehen muss.
|
Ein komplette Runde Mahjong, die aus genau 4 Spielern bestehen muss.
|
||||||
@@ -95,7 +94,6 @@ class Hanchan(models.Model):
|
|||||||
player1 = models.ForeignKey(
|
player1 = models.ForeignKey(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
limit_choices_to={'is_active': True, 'membership': True},
|
|
||||||
related_name='user_hanchan+',
|
related_name='user_hanchan+',
|
||||||
verbose_name=_('Player 1'))
|
verbose_name=_('Player 1'))
|
||||||
player1_input_score = models.IntegerField(_('Score'))
|
player1_input_score = models.IntegerField(_('Score'))
|
||||||
@@ -115,7 +113,6 @@ class Hanchan(models.Model):
|
|||||||
player2 = models.ForeignKey(
|
player2 = models.ForeignKey(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
limit_choices_to={'is_active': True, 'membership': True},
|
|
||||||
related_name='user_hanchan+',
|
related_name='user_hanchan+',
|
||||||
verbose_name=_('Player 2'))
|
verbose_name=_('Player 2'))
|
||||||
player2_input_score = models.IntegerField(_('Score'))
|
player2_input_score = models.IntegerField(_('Score'))
|
||||||
@@ -135,7 +132,6 @@ class Hanchan(models.Model):
|
|||||||
player3 = models.ForeignKey(
|
player3 = models.ForeignKey(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
limit_choices_to={'is_active': True, 'membership': True},
|
|
||||||
related_name='user_hanchan+',
|
related_name='user_hanchan+',
|
||||||
verbose_name=_('Player 3'))
|
verbose_name=_('Player 3'))
|
||||||
player3_input_score = models.IntegerField(_('Score'))
|
player3_input_score = models.IntegerField(_('Score'))
|
||||||
@@ -155,7 +151,6 @@ class Hanchan(models.Model):
|
|||||||
player4 = models.ForeignKey(
|
player4 = models.ForeignKey(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
limit_choices_to={'is_active': True, 'membership': True},
|
|
||||||
related_name='user_hanchan+',
|
related_name='user_hanchan+',
|
||||||
verbose_name=_('Player 4'))
|
verbose_name=_('Player 4'))
|
||||||
player4_input_score = models.IntegerField(_('Score'))
|
player4_input_score = models.IntegerField(_('Score'))
|
||||||
@@ -205,11 +200,11 @@ class Hanchan(models.Model):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.clean_fields()
|
self.clean_fields()
|
||||||
except ValidationError as e:
|
except ValidationError as exception:
|
||||||
print e.update_error_dict(errors)
|
exception.update_error_dict(errors)
|
||||||
return
|
return
|
||||||
|
|
||||||
for i in xrange(1, 5):
|
for i in range(1, 5):
|
||||||
player = getattr(self, 'player%d' % i)
|
player = getattr(self, 'player%d' % i)
|
||||||
input_score = getattr(self, 'player%d_input_score' % i)
|
input_score = getattr(self, 'player%d_input_score' % i)
|
||||||
score_sum += input_score
|
score_sum += input_score
|
||||||
@@ -309,7 +304,7 @@ class Hanchan(models.Model):
|
|||||||
@property
|
@property
|
||||||
def player_list(self):
|
def player_list(self):
|
||||||
player_list = []
|
player_list = []
|
||||||
for i in xrange(1, 5):
|
for i in range(1, 5):
|
||||||
player_list.append({
|
player_list.append({
|
||||||
'user': getattr(self, 'player%d' % i),
|
'user': getattr(self, 'player%d' % i),
|
||||||
'input_score': getattr(self, 'player%d_input_score' % 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'],
|
return sorted(player_list, key=lambda player: player['input_score'],
|
||||||
reverse=True)
|
reverse=True)
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, recalculate=True, **kwargs):
|
||||||
self.season = self.event.mahjong_season or self.start.year
|
self.season = self.event.mahjong_season or self.start.year
|
||||||
self.full_clean()
|
self.full_clean()
|
||||||
|
if recalculate:
|
||||||
self.compute_player_placements()
|
self.compute_player_placements()
|
||||||
|
update_ranking(sender=Hanchan, instance=self)
|
||||||
return models.Model.save(self, **kwargs)
|
return models.Model.save(self, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@@ -435,7 +432,7 @@ class KyuDanRanking(models.Model):
|
|||||||
else:
|
else:
|
||||||
return reverse('player-kyu-score', args=[self.user.username])
|
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
|
Fetches all valid Hanchans from this Player and recalculates his
|
||||||
Kyu/Dan Ranking.
|
Kyu/Dan Ranking.
|
||||||
@@ -449,14 +446,23 @@ class KyuDanRanking(models.Model):
|
|||||||
self.good_hanchans = 0
|
self.good_hanchans = 0
|
||||||
self.won_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()
|
self.update_rank()
|
||||||
valid_hanchans = Hanchan.objects.confirmed_hanchans(user=self.user)
|
valid_hanchans = Hanchan.objects.confirmed_hanchans(user=self.user)
|
||||||
valid_hanchans = valid_hanchans.order_by('start')
|
valid_hanchans = valid_hanchans.order_by('start')
|
||||||
if self.legacy_date:
|
if self.legacy_date:
|
||||||
valid_hanchans = valid_hanchans.filter(start__gt=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()
|
self.hanchan_count += valid_hanchans.count()
|
||||||
for hanchan in valid_hanchans:
|
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.get_playerdata(self.user)
|
||||||
hanchan.bonus_points = 0
|
hanchan.bonus_points = 0
|
||||||
hanchan.player_comment = u""
|
hanchan.player_comment = u""
|
||||||
@@ -469,7 +475,7 @@ class KyuDanRanking(models.Model):
|
|||||||
self.won_hanchans += 1 if hanchan.placement == 1 else 0
|
self.won_hanchans += 1 if hanchan.placement == 1 else 0
|
||||||
self.good_hanchans += 1 if hanchan.placement == 2 else 0
|
self.good_hanchans += 1 if hanchan.placement == 2 else 0
|
||||||
hanchan.update_playerdata(self.user)
|
hanchan.update_playerdata(self.user)
|
||||||
hanchan.save(force_update=True)
|
hanchan.save(recalculate=False)
|
||||||
self.save(force_update=True)
|
self.save(force_update=True)
|
||||||
|
|
||||||
def update_hanchan_points(self, hanchan):
|
def update_hanchan_points(self, hanchan):
|
||||||
@@ -537,7 +543,7 @@ class KyuDanRanking(models.Model):
|
|||||||
if self.dan_points > min_points:
|
if self.dan_points > min_points:
|
||||||
self.dan = dan_rank
|
self.dan = dan_rank
|
||||||
break
|
break
|
||||||
if self.dan > old_dan:
|
if old_dan == None or self.dan > old_dan:
|
||||||
self.wins_in_a_row = 0
|
self.wins_in_a_row = 0
|
||||||
elif self.kyu_points < 1:
|
elif self.kyu_points < 1:
|
||||||
self.kyu_points = 0
|
self.kyu_points = 0
|
||||||
@@ -600,10 +606,16 @@ class SeasonRanking(models.Model):
|
|||||||
|
|
||||||
def update_ranking(sender, instance, **kwargs):
|
def update_ranking(sender, instance, **kwargs):
|
||||||
for user in (instance.player1, instance.player2, instance.player3, instance.player4):
|
for user in (instance.player1, instance.player2, instance.player3, instance.player4):
|
||||||
logger.debug("marking %s's kyu/dan for recalculation", user)
|
logger.debug(
|
||||||
set_dirty(user=user.id)
|
"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:
|
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)
|
set_dirty(user=user.id, season=instance.season)
|
||||||
logger.debug("marking season %d for recalculation.", instance.season)
|
logger.debug("marking season %d for recalculation.", instance.season)
|
||||||
set_dirty(season=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)
|
set_dirty(event=instance.event_id, user=user.id)
|
||||||
|
|
||||||
models.signals.pre_delete.connect(update_ranking, sender=Hanchan)
|
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)
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ Created on 03.10.2011
|
|||||||
|
|
||||||
@author: christian
|
@author: christian
|
||||||
"""
|
"""
|
||||||
from django.conf.urls import * # @UnusedWildImport
|
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
from django.conf.urls import url
|
||||||
import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
url(r'^$', RedirectView.as_view(
|
url(r'^$', RedirectView.as_view(
|
||||||
url='/ranking/mahjong-ladder/', permanent=True)
|
url='/ranking/mahjong-ladder/', permanent=True)
|
||||||
),
|
),
|
||||||
@@ -42,4 +40,4 @@ urlpatterns = patterns(
|
|||||||
name="kyudanranking-list"),
|
name="kyudanranking-list"),
|
||||||
url(r'^mahjong/(?P<order_by>[\+\-\w]+)/$',
|
url(r'^mahjong/(?P<order_by>[\+\-\w]+)/$',
|
||||||
views.KyuDanRankingList.as_view(), name="kyudanranking-list"),
|
views.KyuDanRankingList.as_view(), name="kyudanranking-list"),
|
||||||
)
|
]
|
||||||
|
|||||||
@@ -256,5 +256,4 @@ class PlayerLadderScore(PlayerScore):
|
|||||||
self.season = date.today().year
|
self.season = date.today().year
|
||||||
hanchan_list = models.Hanchan.objects.season_hanchans(
|
hanchan_list = models.Hanchan.objects.season_hanchans(
|
||||||
user=self.user, season=self.season)
|
user=self.user, season=self.season)
|
||||||
print hanchan_list
|
|
||||||
return hanchan_list
|
return hanchan_list
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ Created on 03.10.2011
|
|||||||
|
|
||||||
@author: christian
|
@author: christian
|
||||||
"""
|
"""
|
||||||
from django.conf.urls import * # @UnusedWildImport
|
from django.conf.urls import url
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
from .views import DeleteGame, ListGames, ListPlayerGames, \
|
from .views import DeleteGame, ListGames, ListPlayerGames, \
|
||||||
ListRankings, GameForm
|
ListRankings, GameForm
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'maistar_ranking.views',
|
|
||||||
url('^$', ListRankings.as_view()),
|
url('^$', ListRankings.as_view()),
|
||||||
url(r'^event/(?P<event>[\d]+)/maistar/$',
|
url(r'^event/(?P<event>[\d]+)/maistar/$',
|
||||||
ListGames.as_view(), name="maistar-game-list"),
|
ListGames.as_view(), name="maistar-game-list"),
|
||||||
@@ -28,4 +27,4 @@ urlpatterns = patterns(
|
|||||||
ListPlayerGames.as_view(), name="maistar-player-games"),
|
ListPlayerGames.as_view(), name="maistar-player-games"),
|
||||||
url(r'^player/(?P<username>[\-\.\d\w]+)/maistar/(?P<season>[\d]+)/$',
|
url(r'^player/(?P<username>[\-\.\d\w]+)/maistar/(?P<season>[\d]+)/$',
|
||||||
ListPlayerGames.as_view(), name="maistar-player-games"),
|
ListPlayerGames.as_view(), name="maistar-player-games"),
|
||||||
)
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class ActivationRequest(models.Model):
|
|||||||
verbose_name = _('pending activation')
|
verbose_name = _('pending activation')
|
||||||
verbose_name_plural = _('pending activations')
|
verbose_name_plural = _('pending activations')
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
return _("user registration for %s") % self.user
|
return _("user registration for %s") % self.user
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
@@ -215,7 +215,7 @@ class Membership(AbstractUser):
|
|||||||
verbose_name = _('Membership')
|
verbose_name = _('Membership')
|
||||||
verbose_name_plural = _('Memberships')
|
verbose_name_plural = _('Memberships')
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n fieldset_extras %}
|
{% load i18n fieldset_extras %}
|
||||||
{% load url from future %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "Registration"%}{% endblock %}
|
{% block title %}{% trans "Registration"%}{% endblock %}
|
||||||
{% block teaser%}
|
{% block teaser%}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load url from future %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "Activation sent"%}{% endblock %}
|
{% block title %}{% trans "Activation sent"%}{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load url from future %}
|
|
||||||
|
|
||||||
{% block title %}{% trans 'Login' %}{% endblock %}
|
{% block title %}{% trans 'Login' %}{% endblock %}
|
||||||
{% block description %}Anmelden auf Kasu.at{% endblock %}
|
{% block description %}Anmelden auf Kasu.at{% endblock %}
|
||||||
|
|
||||||
{% block extra_head %}
|
{% block extra_head %}
|
||||||
<link rel="canonical" href="{% url 'django.contrib.auth.views.login' %}"/>
|
<link rel="canonical" href="{% url 'login' %}"/>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block teaser %}<h1>{% trans 'Login' %}</h1>{% endblock %}
|
{% block teaser %}<h1>{% trans 'Login' %}</h1>{% endblock %}
|
||||||
{% block maincontent %}
|
{% block maincontent %}
|
||||||
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
|
<form method="post" action="{% url 'login' %}">
|
||||||
<h2 class="grid_12">Auf der Seite Anmelden</h2>
|
<h2 class="grid_12">Auf der Seite Anmelden</h2>
|
||||||
|
|
||||||
<div class="grid_7">
|
<div class="grid_7">
|
||||||
|
|||||||
@@ -3,26 +3,38 @@ Created on 03.10.2011
|
|||||||
|
|
||||||
@author: christian
|
@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
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
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"),
|
|
||||||
url(r'^activate/(?P<activation_key>[\d\w]+)/$',
|
url(r'^activate/(?P<activation_key>[\d\w]+)/$',
|
||||||
views.ActivateRegistration.as_view(),
|
views.ActivateRegistration.as_view(),
|
||||||
name='membership-activate-registration'),
|
name='membership-activate-registration'),
|
||||||
url(r'^activation_sent/$',
|
url(r'^activation_sent/$',
|
||||||
views.ActivationSent.as_view(),
|
views.ActivationSent.as_view(),
|
||||||
name="membership-registration-complete"),
|
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]+)/$',
|
url(r'^(?P<username>[\-\.\d\w]+)/$',
|
||||||
views.MembershipDetail.as_view(), name='membership-details'),
|
views.MembershipDetail.as_view(), name='membership-details'),
|
||||||
url(r'^(?P<username>[\-\.\d\w]+)/edit/$',
|
url(r'^(?P<username>[\-\.\d\w]+)/edit/$',
|
||||||
views.EditMembership.as_view(), name="membership-edit")
|
views.EditMembership.as_view(), name="membership-edit")
|
||||||
)
|
]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import re
|
|||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils.encoding import smart_unicode, force_unicode
|
from django.utils.encoding import smart_text, force_text
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -29,13 +29,13 @@ class LookupBase(object):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def get_item_label(self, item):
|
def get_item_label(self, item):
|
||||||
return smart_unicode(item)
|
return smart_text(item)
|
||||||
|
|
||||||
def get_item_id(self, item):
|
def get_item_id(self, item):
|
||||||
return smart_unicode(item)
|
return smart_text(item)
|
||||||
|
|
||||||
def get_item_value(self, item):
|
def get_item_value(self, item):
|
||||||
return smart_unicode(item)
|
return smart_text(item)
|
||||||
|
|
||||||
def get_item(self, value):
|
def get_item(self, value):
|
||||||
return value
|
return value
|
||||||
@@ -84,7 +84,7 @@ class LookupRegistry(object):
|
|||||||
|
|
||||||
def register(self, lookup):
|
def register(self, lookup):
|
||||||
self.validate(lookup)
|
self.validate(lookup)
|
||||||
name = force_unicode(lookup.name())
|
name = force_text(lookup.name())
|
||||||
if name in self._registry:
|
if name in self._registry:
|
||||||
raise LookupAlreadyRegistered(u'The name %s is already registered'
|
raise LookupAlreadyRegistered(u'The name %s is already registered'
|
||||||
% name)
|
% name)
|
||||||
@@ -92,7 +92,7 @@ class LookupRegistry(object):
|
|||||||
|
|
||||||
def unregister(self, lookup):
|
def unregister(self, lookup):
|
||||||
self.validate(lookup)
|
self.validate(lookup)
|
||||||
name = force_unicode(lookup.name())
|
name = force_text(lookup.name())
|
||||||
if name not in self._registry:
|
if name not in self._registry:
|
||||||
raise LookupNotRegistered(u'The name %s is not registered' % name)
|
raise LookupNotRegistered(u'The name %s is not registered' % name)
|
||||||
del self._registry[name]
|
del self._registry[name]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from django.conf import settings
|
|||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.forms.utils import flatatt
|
from django.forms.utils import flatatt
|
||||||
from django.utils import formats
|
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.html import conditional_escape
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
@@ -98,7 +98,7 @@ class CheckboxInput(widgets.CheckboxInput):
|
|||||||
if not (
|
if not (
|
||||||
value is True or value is False or value is None or value == ''): # @IgnorePep8
|
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.
|
# 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'<input%s /> %s' % (flatatt(final_attrs), title))
|
return mark_safe(u'<input%s /> %s' % (flatatt(final_attrs), title))
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ class Textarea(widgets.Widget):
|
|||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
|
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
|
||||||
conditional_escape(
|
conditional_escape(
|
||||||
force_unicode(
|
force_text(
|
||||||
value))))
|
value))))
|
||||||
|
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ class LookupMultipleHiddenInput(widgets.MultipleHiddenInput):
|
|||||||
if model and isinstance(v, model):
|
if model and isinstance(v, model):
|
||||||
item = v
|
item = v
|
||||||
v = lookup.get_item_id(item)
|
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_:
|
if id_:
|
||||||
# An ID attribute was given. Add a numeric index as a suffix
|
# An ID attribute was given. Add a numeric index as a suffix
|
||||||
# so that the inputs don't all have the same ID attribute.
|
# so that the inputs don't all have the same ID attribute.
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ Created on 19.10.2011
|
|||||||
|
|
||||||
@author: christian
|
@author: christian
|
||||||
"""
|
"""
|
||||||
from BeautifulSoup import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
#TODO: Nach BeatutifulSoup 4 convertieren
|
||||||
|
|
||||||
|
|
||||||
class HtmlCleaner(object):
|
class HtmlCleaner(object):
|
||||||
@@ -38,7 +39,7 @@ class HtmlCleaner(object):
|
|||||||
tag_removed = False
|
tag_removed = False
|
||||||
|
|
||||||
def clean_attributes(self, tag):
|
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:
|
if attr not in self.ACCEPTABELE_ATTRIBUTES:
|
||||||
del tag[attr]
|
del tag[attr]
|
||||||
elif tag[attr].count('script:'):
|
elif tag[attr].count('script:'):
|
||||||
@@ -57,14 +58,14 @@ class HtmlCleaner(object):
|
|||||||
@param fragment:
|
@param fragment:
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
soup = BeautifulSoup(fragment)
|
soup = BeautifulSoup(fragment, "html.parser")
|
||||||
self.tag_removed = False
|
self.tag_removed = False
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
for tag in soup.findAll(True):
|
for tag in soup.find_all(True):
|
||||||
self.clean_tag(tag)
|
self.clean_tag(tag)
|
||||||
fragment = unicode(soup)
|
fragment = str(soup)
|
||||||
if self.tag_removed:
|
if self.tag_removed:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return fragment
|
return fragment.strip()
|
||||||
|
|||||||
@@ -219,9 +219,9 @@ class Command(BaseCommand):
|
|||||||
css_output = '%s/%s.css' % (CSS_ROOT,
|
css_output = '%s/%s.css' % (CSS_ROOT,
|
||||||
site.domain.replace('.', '_'))
|
site.domain.replace('.', '_'))
|
||||||
|
|
||||||
print _("Compressing CSS for %s") % site.name
|
print("Compressing CSS for {}".format(site.name))
|
||||||
print "Input Dir: %s" % css_input
|
print("Input Dir: {}".format(css_input))
|
||||||
print "Output File: %s" % css_output
|
print("Output File: {}".format(css_output))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(css_input)
|
os.makedirs(css_input)
|
||||||
@@ -232,7 +232,7 @@ class Command(BaseCommand):
|
|||||||
and append their content"""
|
and append their content"""
|
||||||
for file_name in fnmatch.filter(sorted(os.listdir(css_input)),
|
for file_name in fnmatch.filter(sorted(os.listdir(css_input)),
|
||||||
'*.css'):
|
'*.css'):
|
||||||
print ' Adding: %s' % file_name
|
print('Adding: {}'.format(file_name))
|
||||||
with open(os.path.join(css_input, file_name), 'r') as css_file:
|
with open(os.path.join(css_input, file_name), 'r') as css_file:
|
||||||
css += css_file.read()
|
css += css_file.read()
|
||||||
with open(css_output, 'w') as css_file:
|
with open(css_output, 'w') as css_file:
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class Command(BaseCommand):
|
|||||||
js_input = os.path.join(JS_ROOT, site.domain)
|
js_input = os.path.join(JS_ROOT, site.domain)
|
||||||
js_output = '%s/%s.js' % (JS_ROOT, site.domain.replace('.', '_'))
|
js_output = '%s/%s.js' % (JS_ROOT, site.domain.replace('.', '_'))
|
||||||
|
|
||||||
print _("Compressing JavaScript for %s") % site.name
|
print("Compressing JavaScript for {}".format(site.name))
|
||||||
print "Input Dir: %s" % js_input
|
print("Input Dir: {}".format(js_input))
|
||||||
print "Output File: %s" % js_output
|
print("Output File: %s".format(js_output))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(js_input)
|
os.makedirs(js_input)
|
||||||
@@ -39,7 +39,7 @@ class Command(BaseCommand):
|
|||||||
# content
|
# content
|
||||||
js_files = fnmatch.filter(sorted(os.listdir(js_input)), '*.js')
|
js_files = fnmatch.filter(sorted(os.listdir(js_input)), '*.js')
|
||||||
for file_name in js_files:
|
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)
|
input_file_name = os.path.join(js_input, file_name)
|
||||||
with open(input_file_name, 'r') as input_file:
|
with open(input_file_name, 'r') as input_file:
|
||||||
output += input_file.read()
|
output += input_file.read()
|
||||||
|
|||||||
46
src/utils/tests.py
Normal file
46
src/utils/tests.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import unittest
|
||||||
|
import html_cleaner
|
||||||
|
|
||||||
|
|
||||||
|
class HtmlTestCase(unittest.TestCase):
|
||||||
|
known_html = (
|
||||||
|
('<STRONG>Fett!</STRONG>', '<strong>Fett!</strong>'),
|
||||||
|
('<a href="link.html" onclick="do_evil()">Bad Link</a>', '<a href="link.html">Bad Link</a>'),
|
||||||
|
('''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
|
<HTML><HEAD>
|
||||||
|
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
|
||||||
|
<META content="MSHTML 5.50.4919.2200" name=GENERATOR>
|
||||||
|
<STYLE></STYLE>
|
||||||
|
</HEAD>
|
||||||
|
<BODY bgColor=#ffffff>
|
||||||
|
<DIV><FONT face=Arial size=2>Hey Brad;</FONT></DIV>
|
||||||
|
<DIV><FONT face=Arial size=2></FONT> </DIV>
|
||||||
|
<DIV><FONT face=Arial size=2> 1) From your FAQ page at Webalizer.com the README
|
||||||
|
file link in question 19 to <A
|
||||||
|
href="ftp://ftp.mrunix.net/pub/webalizer/README">ftp://ftp.mrunix.net/pub/webalizer/README</A> brings
|
||||||
|
a 404 Page Not Found error message.</FONT></DIV>
|
||||||
|
<DIV><FONT face=Arial size=2></FONT> </DIV>
|
||||||
|
<DIV><FONT face=Arial size=2> 2) </FONT><FONT face=Arial size=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?</FONT></DIV>
|
||||||
|
<DIV><FONT face=Arial size=2></FONT> </DIV>
|
||||||
|
<DIV><FONT face=Arial size=2>XXXXXX XXXXXXX<BR>XXXXXXXXX Web Design<BR><A
|
||||||
|
href="http://www.xxxxxxxxxxxx.com">http://www.xxxxxxxxxxxx.com</A><BR>(xxx)
|
||||||
|
xxx-xxxx</FONT></DIV></BODY></HTML>
|
||||||
|
''',
|
||||||
|
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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()
|
||||||
Reference in New Issue
Block a user