diff --git a/.gitignore b/.gitignore
index abc4b21..aedb730 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.pyc
-htdocs/media/
+htdocs/
+static/
media/
.idea
.gitignore
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index d821048..f758959 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -1,4 +1,6 @@
-
+
+
+
\ No newline at end of file
diff --git a/aggregator/admin.py b/aggregator/admin.py
index 49b7c84..dd7243f 100644
--- a/aggregator/admin.py
+++ b/aggregator/admin.py
@@ -1,6 +1,8 @@
from django.contrib import admin
+
from models import Feed, FeedItem
+
admin.site.register(
Feed,
list_display=["title", "public_url", "last_update", 'is_functional'],
diff --git a/aggregator/feeds.py b/aggregator/feeds.py
index f152dd9..463f753 100644
--- a/aggregator/feeds.py
+++ b/aggregator/feeds.py
@@ -1,4 +1,5 @@
import django.contrib.syndication.views
+
from .models import FeedItem
diff --git a/aggregator/management/commands/update-feeds.py b/aggregator/management/commands/update-feeds.py
index 4760c25..7e71b17 100644
--- a/aggregator/management/commands/update-feeds.py
+++ b/aggregator/management/commands/update-feeds.py
@@ -3,9 +3,10 @@ Update feeds for Django community page. Requires Mark Pilgrim's excellent
Universal Feed Parser (http://feedparser.org)
"""
-from aggregator.models import Feed
from django.core.management.base import BaseCommand
+from aggregator.models import Feed
+
class Command(BaseCommand):
help = "Updates all RSS Feeds"
diff --git a/aggregator/models.py b/aggregator/models.py
index 892a286..ad22620 100644
--- a/aggregator/models.py
+++ b/aggregator/models.py
@@ -5,14 +5,16 @@ Created on 05.02.2011
"""
from datetime import datetime, timedelta
+import HTMLParser
+import urllib2
+
from django.conf import settings
from django.contrib.sites.models import Site
from django.utils import timezone
-from utils.html5 import models
-import HTMLParser
import django.db.models
import feedparser
-import urllib2
+
+from utils.html5 import models
class FeedManager(django.db.models.Manager):
@@ -35,7 +37,7 @@ class FeedItemManager(django.db.models.Manager):
return self.select_related().filter(feed__site=site)[:max_items]
-class Feed(models.Model):
+class Feed(django.db.models.Model):
title = models.CharField(max_length=500)
site = models.ForeignKey(Site)
feed_url = models.URLField(unique=True, max_length=255)
@@ -51,7 +53,8 @@ class Feed(models.Model):
parsed_feed = feedparser.parse(self.feed_url)
html_parser = HTMLParser.HTMLParser()
- if parsed_feed.bozo and type(parsed_feed.bozo_exception) == urllib2.URLError:
+ if parsed_feed.bozo and type(
+ parsed_feed.bozo_exception) == urllib2.URLError:
self.is_functional = False
return self.save()
@@ -68,16 +71,22 @@ class Feed(models.Model):
feed_entry.get("content", u"")
))
)
- date_modified = feed_entry.get("published_parsed", parsed_feed.get("published_parsed", timezone.now))
- date_modified = timezone.make_aware(datetime(*date_modified[:6]), timezone.get_current_timezone())
+ date_modified = feed_entry.get(
+ "published_parsed",
+ parsed_feed.get("published_parsed",
+ timezone.now))
+ date_modified = timezone.make_aware(
+ datetime(*date_modified[:6]),
+ timezone.get_current_timezone())
- feed_item, updated = self.feed_items.get_or_create(guid=guid,
- defaults={
- 'title': title,
- 'link': link,
- 'summary': summary,
- 'date_modified': date_modified
- })
+ feed_item, updated = self.feed_items.get_or_create(
+ guid=guid,
+ defaults={
+ 'title': title,
+ 'link': link,
+ 'summary': summary,
+ 'date_modified': date_modified
+ })
feed_item.save()
self.last_update = timezone.now()
return self.save()
@@ -86,7 +95,7 @@ class Feed(models.Model):
ordering = ("title",)
-class FeedItem(models.Model):
+class FeedItem(django.db.models.Model):
feed = models.ForeignKey(Feed, related_name='feed_items')
title = models.CharField(max_length=500)
link = models.URLField(max_length=500)
diff --git a/aggregator/sitemaps.py b/aggregator/sitemaps.py
index e8ddf2d..a447596 100644
--- a/aggregator/sitemaps.py
+++ b/aggregator/sitemaps.py
@@ -1,7 +1,9 @@
from django.contrib.sitemaps import Sitemap
+
from models import FeedItem
+
# noinspection PyMethodMayBeStatic
class FeedItemSitemap(Sitemap):
changefreq = "never"
diff --git a/aggregator/templatetags/aggregator.py b/aggregator/templatetags/aggregator.py
index 0e7a5cd..d9f4d79 100644
--- a/aggregator/templatetags/aggregator.py
+++ b/aggregator/templatetags/aggregator.py
@@ -1,9 +1,9 @@
from django import template
+
from models import Feed
class FeedListNode(template.Node):
-
def __init__(self, varname):
self.varname = varname
@@ -26,5 +26,6 @@ def do_get_feed_list(parser, token):
"First argument to '%s' tag must be 'as'" % bits[0]
return FeedListNode(bits[2])
+
register = template.Library()
register.tag('get_feed_list', do_get_feed_list)
diff --git a/cleanup.sh b/cleanup.sh
index 08081c5..468fa96 100755
--- a/cleanup.sh
+++ b/cleanup.sh
@@ -1,12 +1,23 @@
#!/bin/sh
echo "aktualisiere Übersetzungen..."
-cd src
-./manage.py makemessages -l de
-./manange.py compilemessages -a
+unset DJANGO_SETTINGS_MODULE
+for dir in *
+ do
+ if [ -d $dir/locale ]
+ then
+ echo -n "$dir: "
+ cd $dir
+ django-admin.py makemessages -l de
+ cd ..
+ fi
+ done
+sleep 5s
+export DJANGO_SETTINGS_MODULE="kasu.settings.production"
+./manage.py compilemessages
echo "lösche den Python Compiler Cache..."
find . -name "*.pyc" -exec rm -rf {} \;
-touch kasu.wsgi
./manage.py collectstatic --noinput
./manage.py generateimages
+touch kasu/wsgi.py
diff --git a/gallery/forms.py b/gallery/forms.py
index e731f3d..ae00c98 100644
--- a/gallery/forms.py
+++ b/gallery/forms.py
@@ -3,11 +3,13 @@ Created on 03.10.2011
@author: christian
"""
-from . import models
from django import forms
from django.utils.translation import ugettext as _
from django.contrib.auth import get_user_model
-from utils.html5.widgets import DateTimeInput
+
+from . import models
+from events.models import Event
+
user_query = get_user_model().objects.all()
@@ -15,8 +17,8 @@ user_query = get_user_model().objects.all()
class PhotoUploadForm(forms.Form):
error_css_class = 'error'
required_css_class = 'required'
- photographer = forms.ModelChoiceField(user_query, required=True,)
- event = forms.ModelChoiceField(models.Event.objects.all(), required=True,)
+ photographer = forms.ModelChoiceField(user_query, required=True, )
+ event = forms.ModelChoiceField(Event.objects.all(), required=True, )
upload = forms.FileField(
label=_('Images'),
required=True,
@@ -38,20 +40,3 @@ class EditPhotoForm(forms.ModelForm):
fields = ('event', 'name', 'description', 'photographer',
'anchor_horizontal', 'anchor_vertical',
'created_date', 'on_startpage')
-
-
-class EventForm(forms.ModelForm):
- error_css_class = 'error'
- required_css_class = 'required'
-
- start = forms.DateTimeField(
- label=_('start'), required=True,
- widget=DateTimeInput() # widget=SplitDateTimeWidget()
- )
- end = forms.DateTimeField(
- label=_('end'), required=False,
- widget=DateTimeInput() # widget=SplitDateTimeWidget()
- )
-
- class Meta(object):
- model = models.Event
diff --git a/gallery/models.py b/gallery/models.py
index 6217ccc..929d3bd 100644
--- a/gallery/models.py
+++ b/gallery/models.py
@@ -5,29 +5,11 @@ import os
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
-from django.template.defaultfilters import slugify
-from django.utils.timezone import now
from django.utils.translation import ugettext as _
-from imagekit import ImageSpec
-import imagekit
-from imagekit.models import ImageSpecField
-from pilkit import processors
import pyexiv2
-from utils import COUNTRIES, OverwriteStorage
-
-
-CHOICES_HORIZONTAL = (
- (0.00000001, _('left')),
- (0.5, _('center')),
- (1, _('right'))
-)
-
-CHOICES_VERTICAL = (
- (0.00000001, _('top')),
- (0.5, _('middle')),
- (1, _('bottom'))
-)
+from utils import OverwriteStorage
+from kasu import image_models
def get_upload_path(instance, filename):
@@ -42,231 +24,10 @@ def get_upload_path(instance, filename):
@type filename: String
"""
extension = filename[filename.rfind('.') + 1:]
- if isinstance(instance, Event):
- if instance.id:
- return "events/%s.%s" % (instance.id, extension)
- else:
- return "events/%s.%s" % (slugify(instance.name), extension)
- elif isinstance(instance, Location):
- if instance.id:
- return "events/location/%s.%s" % (instance.id, extension)
- else:
- return "events/location/%s.%s" % (instance.id, extension)
- elif isinstance(instance, Photo):
+ if isinstance(instance, Photo):
return "events/%s/%s" % (instance.event.id, filename)
-def post_save_image(sender, instance=None, created=False, raw=False, **kwargs):
- """
- Reganerate the images.
- """
- os.remove(instance.display.path)
- os.remove(instance.callout.path)
- os.remove(instance.thumbnail.path)
-
- """
- instance.callout.generate(force=True)
- instance.display.generate(force=True)
- instance.thumbnail.generate(force=True)
- """
-
-
-class CalloutImage(ImageSpec):
- format = 'PNG'
- width = 940
- height = 300
-
- @property
- def processors(self):
- model, field_name = imagekit.utils.get_field_info(self.source) # @UnusedVariable @IgnorePep8
- anchor = model.get_anchor()
- if anchor:
- return [processors.Transpose(), processors.ResizeToFill(
- width=self.width,
- height=self.height, anchor=anchor
- )]
- else:
- return [processors.Transpose(), processors.SmartResize(
- width=self.width,
- height=self.height
- )]
-
-
-class DisplayImage(ImageSpec):
- format = 'PNG'
- processors = [processors.Transpose(),
- processors.ResizeToFit(width=940, height=940, upscale=False)]
-
-
-class ThumbnailImage(CalloutImage):
- format = 'PNG'
- width = 140
- height = 140
-
-
-imagekit.register.generator('kasu:image:callout', CalloutImage)
-imagekit.register.generator('kasu:image:display', DisplayImage)
-imagekit.register.generator('kasu:image:thumbnail', ThumbnailImage)
-
-
-class ImageModel(models.Model):
- callout = ImageSpecField(source='image', id='kasu:image:callout')
- display = ImageSpecField(source='image', id='kasu:image:display')
- thumbnail = ImageSpecField(source='image', id='kasu:image:thumbnail')
-
- def get_anchor(self):
- try:
- anchor_horizontal = getattr(self, 'anchor_horizontal')
- anchor_vertical = getattr(self, 'anchor_vertical')
- except AttributeError:
- return None
- if anchor_horizontal and anchor_vertical:
- return self.anchor_horizontal, self.anchor_vertical
- else:
- return None
-
- class Meta:
- abstract = True
-
-
-class EventManager(models.Manager):
- def current_event(self):
- try:
- current = self.filter(start__lte=now())
- current = current.filter(end__gte=now())
- return current.order_by('start', 'end')[0]
- except:
- return None
-
- def next_event(self):
- try:
- return self.filter(start__gt=now()).order_by('start', 'end')[0]
- except:
- return None
-
- def archive(self):
- return self.filter(start__lt=now())
-
- def upcoming(self, limit=3):
- result = self.filter(start__gt=now()).order_by('start', 'end')
- if limit:
- return result[1:(limit + 1)]
- else:
- return result
-
-
-class Event(ImageModel):
- name = models.CharField(_('Name'), max_length=255)
- description = models.TextField(_("Description"), blank=True)
- location = models.ForeignKey('Location')
- start = models.DateTimeField(_('Start'))
- end = models.DateTimeField(_('End'), blank=True, null=True)
- url = models.URLField(_('Homepage'), blank=True)
- image = models.ImageField(_("Image"), upload_to=get_upload_path,
- storage=OverwriteStorage(), blank=True, null=True)
- is_tournament = models.BooleanField(_('Tournament'), default=False,
- help_text=_(u'This event is a tournament, different rules apply for \
- the kyu ranking.'))
- photo_count = models.PositiveIntegerField(default=0, editable=False)
- event_series = models.ForeignKey('Event', blank=True, null=True,
- on_delete=models.SET_NULL, editable=False,
- verbose_name=_('Event Series'),
- help_text=_(u'Wenn dieser Event zu einer Veranstaltungsreihe gehört \
- werden Ort, Beschreibung, Bild und Homepage von dem hier angegebenen \
- Event übernommen.'))
- objects = EventManager()
-
- class Meta(object):
- verbose_name = _('Event')
- verbose_name_plural = _('Events')
- ordering = ('-start', '-end',)
-
- def __unicode__(self):
- try:
- return "%(name)s (%(date)s)" % {'name': self.name,
- 'date': self.start.date()}
- except:
- return "New Event Model"
-
- def get_absolute_url(self):
- kwargs = {
- 'pk': self.id,
- 'year': self.start.strftime('%Y'),
- 'month': self.start.strftime('%m')
- }
- return reverse('event-detail', kwargs=kwargs)
-
- def get_edit_url(self):
- kwargs = {
- 'pk': self.id,
- 'year': self.start.strftime('%Y'),
- 'month': self.start.strftime('%m')
- }
- return reverse('event-form', kwargs=kwargs)
-
- def get_callout(self):
- if self.image:
- return self.callout
- elif self.photo_set.count():
- return self.photo_set.all().order_by('?')[0].callout
- elif self.location.image:
- return self.location.callout
- else:
- return None
-
- def get_thumbnail(self):
- if self.image:
- return self.thumbnail
- elif self.photo_set.count():
- return self.photo_set.all().order_by('?')[0].thumbnail
- elif self.location.image:
- return self.location.thumbnail
- else:
- return None
-
- def save(self, **kwargs):
- if self.event_series:
- master_event = self.event_series
- self.description = master_event.description
- self.location = master_event.location
- self.url = master_event.url
- self.image = master_event.image
- self.photo_count = self.photo_set.count()
- models.Model.save(self, **kwargs)
-
- # Update the rest of the event series:
- for sub_event in Event.objects.filter(event_series=self):
- sub_event.save()
-
- # Update the Hanchans if necesery:
- for hanchan in self.hanchan_set.all():
- hanchan.save()
-
-
-class Location(ImageModel):
- name = models.CharField(_("Name"), max_length=200)
- description = models.TextField(_("Description"), blank=True)
- image = models.ImageField(_("Image"), upload_to=get_upload_path,
- storage=OverwriteStorage(), blank=True, null=True)
- url = models.URLField(_('Homepage'), blank=True)
- postal_code = models.CharField(_('Postal Code'), max_length=6)
- street_address = models.CharField(_('Street Address'), max_length=127)
- locality = models.CharField(_('Locality'), max_length=127)
- country = models.CharField(_('Country'), max_length=2, choices=COUNTRIES)
-
- class Meta(object):
- verbose_name = _('Venue')
- verbose_name_plural = _('Venues')
-
- def __unicode__(self):
- return self.name
-
- @property
- def address(self):
- address = (self.street_address, self.locality, self.country,)
- return ','.join(address)
-
-
class PhotoManager(models.Manager):
def get_random(self, startpage=True):
if startpage:
@@ -279,26 +40,26 @@ class PhotoManager(models.Manager):
return Photo()
-class Photo(ImageModel):
+class Photo(image_models.ImageModel):
name = models.CharField(_("Name"), max_length=100, blank=True)
image = models.ImageField(_("Image"), upload_to=get_upload_path,
storage=OverwriteStorage())
anchor_horizontal = models.FloatField(
_('horizontal Anchorpoint'),
- choices=CHOICES_HORIZONTAL,
+ choices=image_models.CHOICES_HORIZONTAL,
blank=True, null=True,
help_text='Der Ankerpunkt ist der interessante Teil des Bildes,\
welcher nie abgeschnitten werden darf'
)
anchor_vertical = models.FloatField(
_('vertical Anchorpoint'),
- choices=CHOICES_VERTICAL,
+ choices=image_models.CHOICES_VERTICAL,
blank=True, null=True,
help_text='Wenn kein Ankerpunkt von Hand (horizontal und vertikal)\
festgelegt wird, versucht die Software diesen selbst zu erraten.'
)
- event = models.ForeignKey(Event)
+ event = models.ForeignKey('events.Event')
description = models.TextField(
_("Description"),
max_length=300,
@@ -321,10 +82,12 @@ class Photo(ImageModel):
orientation = 1
class Meta:
+ get_latest_by = "created_date"
+ ordering = ["created_date"]
+ db_table = 'events_photo'
verbose_name = _('Event Image')
verbose_name_plural = _('Event Images')
- ordering = ["created_date"]
- get_latest_by = "created_date"
+
def __unicode__(self):
return os.path.basename(self.image.name)
@@ -395,9 +158,14 @@ class Photo(ImageModel):
Triggers to save related Event to save. This should force an update for
the denormalized Photo count.
"""
- ImageModel.save(self, **kwargs)
+ super(Photo, self).save()
self.save_metadata()
- self.event.save()
-models.signals.post_save.connect(post_save_image, sender=Photo)
+def update_event(sender, instance=None, created=False, raw=False, **kwargs):
+ image_models.regenerate_image_cache(sender, instance=instance)
+ instance.event.save()
+
+
+models.signals.post_save.connect(update_event, sender=Photo)
+models.signals.post_delete.connect(update_event, sender=Photo)
diff --git a/gallery/templates/gallery/photo_confirm_delete.html b/gallery/templates/gallery/photo_confirm_delete.html
index 50475f9..ba444c1 100644
--- a/gallery/templates/gallery/photo_confirm_delete.html
+++ b/gallery/templates/gallery/photo_confirm_delete.html
@@ -1,4 +1,4 @@
-{% extends "base.html" %}
+{% extends "events/event_detail.html" %}
{% load i18n comments %}
{% block maincontent %}
diff --git a/gallery/templates/gallery/photo_detail.html b/gallery/templates/gallery/photo_detail.html
index aae31b2..e7392b5 100644
--- a/gallery/templates/gallery/photo_detail.html
+++ b/gallery/templates/gallery/photo_detail.html
@@ -1,4 +1,4 @@
-{% extends "events/photo_list.html" %}
+{% extends "gallery/photo_list.html" %}
{% load i18n comments %}
{% block title %} {{ photo.name }} - {{ photo.event.name }} {% endblock %}
@@ -22,35 +22,36 @@
Next
{% endif %}
+
{{ photo.description }}
+
- {% if perms.events.change_photo %}
+
+ - {% trans 'Photographer' %}: {{ photo.photographer }}
+ - {% trans 'on' %} {{ photo.created_date }}
+
+{% endblock %}
+
+{% block comment %}
+ {% render_comment_list for photo %}
+ {% render_comment_form for photo %}
+{% endblock %}
+
+{% block buttonbar %}
+{% if perms.events.change_photo %}
- {% else %}
- {{ photo.description }}
-
-
- - {% trans 'Photographer' %}: {{ photo.photographer }}
- - {% trans 'on' %} {{ photo.created_date }}
-
- {% endif %}
-
- {% render_comment_list for photo %}
- {% render_comment_form for photo %}
+{% endif %}
{% endblock %}
diff --git a/gallery/templates/gallery/photo_upload.html b/gallery/templates/gallery/photo_upload.html
index 312e06c..ea86dcb 100644
--- a/gallery/templates/gallery/photo_upload.html
+++ b/gallery/templates/gallery/photo_upload.html
@@ -1,4 +1,4 @@
-{% extends "events/photo_gallery.html" %}
+{% extends "events/event_detail.html" %}
{% load i18n comments %}
{% block maincontent %}
diff --git a/gallery/urls.py b/gallery/urls.py
index e69de29..174fdbd 100644
--- a/gallery/urls.py
+++ b/gallery/urls.py
@@ -0,0 +1,18 @@
+# -*- encoding: utf-8 -*-
+from django.conf.urls import patterns, url
+
+from .views import *
+
+urlpatterns = patterns(
+ '',
+ url(r'^$', EventGallery.as_view(), name='event-gallery'),
+ url(r'^(?P[\d]+)/$', EventPhotoList.as_view(),
+ name='event-photo-list'),
+ url(r'^(?P[\d]+)/upload/$', EventPhotoUpload.as_view(),
+ name='event-photo-upload'),
+ url(r'^(?P[\d]+)/(?P[\d]+)/$', EventPhoto.as_view(),
+ name='event-photo'),
+ url(r'^delete/(?P[\d]+)/$', DeleteEventPhoto.as_view(),
+ name='delete-event-photo'),
+ url(r'^upload/$', EventPhotoUpload.as_view(), name='event-photo-upload'),
+)
\ No newline at end of file
diff --git a/gallery/views.py b/gallery/views.py
index 7b28829..a70e921 100644
--- a/gallery/views.py
+++ b/gallery/views.py
@@ -5,159 +5,55 @@ from datetime import timedelta
from django.contrib.auth.decorators import permission_required
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
-from django.http import HttpResponse, Http404
+from django.http import Http404
from django.shortcuts import redirect
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.views import generic
-from icalendar import Calendar, Event
import pyexiv2
-from utils.mixins import PermissionRequiredMixin
-
-from . import models, forms
+from events.models import Event
+from .models import Photo
+from . import forms
class DeleteEventPhoto(generic.DeleteView):
- model = models.Photo
- """
- def get_object(self, queryset=None):
- return models.Photo.objects.get(pk=self.kwargs['pk'])
- """
+ model = Photo
def get_success_url(self):
return reverse('event-photo-list', args=[self.object.event.id])
+ def get_context_data(self, **kwargs):
+ context = super(DeleteEventPhoto, self).get_context_data()
+ context['event'] = self.object.event
+ return context
+
@method_decorator(permission_required('events.delete_photo'))
def dispatch(self, *args, **kwargs):
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
-class EventArchiveIndex(generic.ArchiveIndexView):
- allow_empty = True
- context_object_name = 'event_list'
- date_field = 'start'
- model = models.Event
- queryset = model.objects.all()
- paginate_by = 15
-
-
- def get_context_data(self, **kwargs):
- context = generic.ArchiveIndexView.get_context_data(self, **kwargs)
- context['is_archive'] = True
- return context
-
-
-class EventArchiveMonth(generic.MonthArchiveView):
- date_field = 'start'
- make_object_list = True
- model = models.Event
- month_format = '%m'
- paginate_by = 15
- template_name = 'events/event_archive.html'
-
- def get_context_data(self, **kwargs):
- context = generic.MonthArchiveView.get_context_data(self, **kwargs)
- context['is_archive'] = True
- return context
-
-
-class EventArchiveYear(generic.YearArchiveView):
- date_field = 'start'
- make_object_list = True
- model = models.Event
- paginate_by = 15
- template_name = 'events/event_archive.html'
- year_format = '%Y'
-
- def get_context_data(self, **kwargs):
- context = generic.YearArchiveView.get_context_data(self, **kwargs)
- context['is_archive'] = True
- return context
-
-
-class EventDetail(generic.DetailView):
- model = models.Event
-
- def get_context_data(self, **kwargs):
- context = generic.DetailView.get_context_data(self, **kwargs)
- context['form'] = forms.PhotoUploadForm(initial={'event': self.object, 'photographer': self.request.user})
- return context
-
-
-class EventForm(PermissionRequiredMixin, generic.UpdateView):
- form_class = forms.EventForm
- permission_required = 'events.add_event'
-
- def get_object(self, queryset=None):
- """
- If an id has been submitted, try return the existing Event for an update,
- else creates a new one.
- @param queryset:
- """
- if self.kwargs.get('pk'):
- event = models.Event.objects.get(pk=self.kwargs['pk'])
- if event.event_series:
- return event.event_series
- else:
- return event
- else:
- return models.Event()
-
-
class EventGallery(generic.ListView):
- template_name = 'events/photo_gallery.html'
- queryset = models.Event.objects.filter(start__lt=timezone.now(), photo_count__gt=0)
+ template_name = 'gallery/photo_gallery.html'
+ queryset = Event.objects.filter(start__lt=timezone.now(), photo_count__gt=0)
paginate_by = 12
-class EventListIcal(generic.View):
- """
- Generates an returns an iCal File with all upcoming events.
- """
-
- def add_event(self, event):
- ics_event = Event()
- dtstart = timezone.localtime(event.start)
- dtend = timezone.localtime(event.end)
-
- ics_event.add('DTSTART', dtstart)
- ics_event.add('SUMMARY', event.name)
- ics_event.add('DESCRIPTION', event.description)
- ics_event.add('LOCATION', event.location.address)
- ics_event.add('URL', 'http://www.kasu.at' + event.get_absolute_url())
- ics_event['UID'] = 'event-%d@www.kasu.at' % event.pk
- ics_event.add('PRIORITY', 5)
- if event.end:
- ics_event.add('DTEND', dtend)
- self.calendar.add_component(ics_event)
-
- def get(self, request, *args, **kwargs):
- response = HttpResponse(mimetype="text/calendar; charset=UTF-8")
- self.calendar = Calendar()
- self.calendar.add('prodid', 'http://www.kasu.at/')
- self.calendar.add('version', '2.0')
- for event in models.Event.objects.upcoming(limit=None):
- self.add_event(event)
- response.write(self.calendar.to_ical())
- return response
-
-
class EventPhoto(generic.UpdateView):
form_class = forms.EditPhotoForm
- model = models.Photo
- template_name = 'events/photo_detail.html'
+ model = Photo
+ template_name = 'gallery/photo_detail.html'
def get_context_data(self, **kwargs):
context = super(EventPhoto, self).get_context_data()
- event = models.Event.objects.get(id=self.kwargs['event'])
- context['event'] = event
+ context['event'] = self.object.event
return context
def post(self, request, *args, **kwargs):
- if request.POST.get('rotate') and request.user.has_perm('events.change_photo'):
- photo = models.Photo.objects.get(pk=kwargs['pk'])
+ if request.POST.get('rotate') and request.user.has_perm(
+ 'events.change_photo'):
+ photo = Photo.objects.get(pk=kwargs['pk'])
photo.rotate(request.POST['rotate'])
# return redirect(photo.get_absolute_url())
return self.get(request)
@@ -172,20 +68,21 @@ class EventPhotoList(generic.ListView):
def get_context_data(self, **kwargs):
context = generic.ListView.get_context_data(self, **kwargs)
context['event'] = self.event
- context['form'] = forms.PhotoUploadForm(initial={'event': self.event, 'photographer': self.request.user})
+ context['form'] = forms.PhotoUploadForm(
+ initial={'event': self.event, 'photographer': self.request.user})
return context
def get_queryset(self):
try:
- self.event = models.Event.objects.get(id=self.kwargs['event'])
- return models.Photo.objects.filter(event=self.event)
- except models.Event.DoesNotExist:
+ self.event = Event.objects.get(id=self.kwargs['event'])
+ return Photo.objects.filter(event=self.event)
+ except Event.DoesNotExist:
raise Http404(_('Event does not exist'))
class EventPhotoUpload(generic.FormView):
form_class = forms.PhotoUploadForm
- template_name = 'events/photo_upload.html'
+ template_name = 'gallery/photo_upload.html'
@method_decorator(permission_required('events.add_photo'))
def dispatch(self, *args, **kwargs):
@@ -193,7 +90,7 @@ class EventPhotoUpload(generic.FormView):
def get_context_data(self, **kwargs):
context = generic.FormView.get_context_data(self, **kwargs)
- context['event_list'] = models.Event.objects.archive()[:12]
+ context['event_list'] = Event.objects.archive()[:12]
return context
def get_initial(self):
@@ -208,14 +105,16 @@ class EventPhotoUpload(generic.FormView):
"""
"""
- self.event = models.Event.objects.get(id=self.request.REQUEST.get('event'))
- photographer = self.request.POST.get('photographer', self.request.user.id)
+ self.event = Event.objects.get(
+ id=self.request.REQUEST.get('event'))
+ photographer = self.request.POST.get('photographer',
+ self.request.user.id)
photographer = get_user_model().objects.get(id=photographer)
self.counter = 1
for upload in self.request.FILES.getlist('upload'):
name = upload.name
created_date, description = self.read_exif(upload)
- photo = models.Photo(
+ photo = Photo(
event=self.event,
photographer=photographer,
image=upload,
@@ -241,7 +140,3 @@ class EventPhotoUpload(generic.FormView):
description = ''
return created_date, description
-
-class UpcomingEvents(generic.ListView):
- queryset = models.Event.objects.upcoming(limit=None)
- paginate_by = 16
diff --git a/kasu/static/css/common.css b/kasu/static/css/common.css
index 7f0584d..bb77e00 100644
--- a/kasu/static/css/common.css
+++ b/kasu/static/css/common.css
@@ -299,46 +299,28 @@ ul.info li {
}
/** PAGINATOR **/
-.paginator {
- clear: both;
- border: 1px solid #d3d7cf;
- border-radius: 10px;
- text-align: center;
- background-color: #f9f9f9;
- box-shadow: inset 0px 1px 0px 0px #ffffff;
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #f9f9f9
- ), color-stop(1, #e9e9e9) );
- background: -moz-linear-gradient(center top, #f9f9f9 5%, #e9e9e9 100%);
- padding: 4px 10px 2px 10px;
+.pagination {
+ text-align:center
}
-.paginator a, .paginator .current {
+.pagination a, .pagination .current, .pagination .next, .pagination .previous {
display: inline-block;
- margin: 0px 2px;
- padding: 2px;
- min-width: 17px;
- color: #2e3436;
- text-decoration: none;
- border-radius: 5px;
+ text-decoration: none;
+ padding: 0 0.5em 0 0.5em;
}
-.paginator .current {
- border: none;
- color: #a40000;
- background: #fff;
- border-radius: 5px;
-}
-
-.paginator .next {
- display: inline-block;
+.pagination .next {
float: right;
+ background: none;
}
-.paginator .prev {
- display: inline-block;
+
+.pagination .previous {
float: left;
+ background: none;
}
+
.center {
text-align: center;
}
@@ -403,4 +385,4 @@ ul.tabs li.active a {border-bottom: 3px solid #bc0a19; color: #bc0a19}
}
fieldset.comment {padding: 0}
fieldset.comment legend {margin-left: 15px}
-fieldset.comment .buttonbar {margin: 0; width: 100%}
\ No newline at end of file
+fieldset.comment .buttonbar {margin: 0; width: 100%}
diff --git a/kasu/static/css/desktop.css b/kasu/static/css/desktop.css
index c6c54ff..24167fd 100644
--- a/kasu/static/css/desktop.css
+++ b/kasu/static/css/desktop.css
@@ -136,14 +136,14 @@ ul.main_menu {padding:0px;}
width: 920px;
}
-#navigation {
+#navigation, .pagination {
clear: both;
background: url(../img/navigation-bg.png) no-repeat left top;
height: 56px;
list-style: none;
margin: 0 auto;
- padding: 8px 0 0 30px;
- width: 920px;
+ padding: 8px 35px 0px 25px;
+ width: 900px;
}
#navigation a {
@@ -434,6 +434,23 @@ ul.tabs li.active a {
text-shadow: 1px 1px 0px #98231a;
}
+.pagination a, .pagination .current, .pagination .next, .pagination .previous {
+ display: inline-block;
+ padding: 2px;
+ color: #FFF;
+ font-weight: bold;
+ height: 33px;
+ text-decoration: none;
+ padding: 17px 0.5em 0 0.5em;
+}
+
+.pagination .current {
+ color: #a40000;
+}
+
+.pagination .disabled {color: #ccc}
+
+
img.avatar {
border: none;
box-shadow: 2px 2px 2px #888;
diff --git a/kasu/static/css/mobile.css b/kasu/static/css/mobile.css
index a900b98..77aa61f 100644
--- a/kasu/static/css/mobile.css
+++ b/kasu/static/css/mobile.css
@@ -337,6 +337,12 @@ fieldset ul li {
}
ul.tabs {margin-top:1em;}
-.paginator {clear:both;}
+.pagination {clear:both;}
+.pagination a, .pagination .current, .pagination .next, .pagination .previous {
+ display: inline-block;
+ text-decoration: none;
+ padding: 0 0.5em 0 0.5em;
+}
+
.gallery {float: left; width:150px; height:150px; margin: 10px;}
-.gallery h3 {font-size: 12pt;}
\ No newline at end of file
+.gallery h3 {font-size: 12pt;}
diff --git a/kasu/templates/paginator.html b/kasu/templates/paginator.html
index 59b09d2..7db6853 100644
--- a/kasu/templates/paginator.html
+++ b/kasu/templates/paginator.html
@@ -1,20 +1,22 @@
{% load i18n %}
-
-{% if page_obj.has_previous %}
-
{% trans "Prev" %}
-{% else %}
-
{% trans "Prev" %}
-{% endif %}
-{% for page in paginator.page_range %}
- {% ifequal page_obj.number page %}
-
{{page}}
- {% else %}
-
{{page}}
- {% endifequal %}
-{% endfor %}
-{% if page_obj.has_next %}
-
{% trans "Next" %} 
-{% else %}
-
{% trans "Next" %} 
-{% endif %}
-
\ No newline at end of file
+
+
diff --git a/mahjong_ranking/__init__.py b/mahjong_ranking/__init__.py
index 62a612a..7879747 100644
--- a/mahjong_ranking/__init__.py
+++ b/mahjong_ranking/__init__.py
@@ -30,7 +30,6 @@ DAN_RANKS = (
DAN_RANKS_DICT = dict([(dan, points) for points, dan in DAN_RANKS])
MIN_HANCHANS_FOR_LADDER = 10
-
logger = getLogger('kasu.mahjong_ranking')
diff --git a/mahjong_ranking/admin.py b/mahjong_ranking/admin.py
index ae10470..0958ee4 100644
--- a/mahjong_ranking/admin.py
+++ b/mahjong_ranking/admin.py
@@ -7,9 +7,10 @@ Created on 19.09.2011
"""
# import stuff we need from django
from django.contrib import admin
+from django.utils.translation import ugettext as _
+
from . import models, set_dirty
from forms import PlayerFormSet
-from django.utils.translation import ugettext as _
def recalculate(modeladmin, request, queryset):
@@ -27,7 +28,10 @@ def recalculate(modeladmin, request, queryset):
set_dirty(season=ranking_season.id)
elif isinstance(modeladmin, LadderRankingAdmin):
for ladder_ranking in queryset:
- set_dirty(user=ladder_ranking.user_id, season=ladder_ranking.season_id) # @IgnorePep8
+ set_dirty(user=ladder_ranking.user_id,
+ season=ladder_ranking.season_id) # @IgnorePep8
+
+
recalculate.short_description = _("Recalculate")
@@ -35,7 +39,7 @@ class PlayerInline(admin.TabularInline):
extra = 4
formset = PlayerFormSet
readonly_fields = ('placement', 'kyu_points', 'dan_points', 'bonus_points',
- 'comment',)
+ 'comment',)
max_num = 4
model = models.Player
@@ -43,7 +47,7 @@ class PlayerInline(admin.TabularInline):
class EventRankingAdmin(admin.ModelAdmin):
list_filter = ['event']
list_display = ('placement', 'user', 'event', 'avg_placement', 'avg_score',
- 'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty')
+ 'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty')
list_display_links = ('user',)
actions = [recalculate]
@@ -53,7 +57,7 @@ class HanchanAdmin(admin.ModelAdmin):
date_hierarchy = 'start'
list_filter = ['season', 'event']
list_display = ('event', 'start', 'player_names', 'comment',
- 'confirmed', 'valid', 'check_validity')
+ 'confirmed', 'valid', 'check_validity')
inlines = (PlayerInline,)
readonly_fields = ('valid', 'check_validity')
@@ -66,13 +70,14 @@ class HanchanAdmin(admin.ModelAdmin):
class KyuDanAdmin(admin.ModelAdmin):
actions = [recalculate]
list_display = ('user', 'kyu', 'kyu_points', 'dan', 'dan_points',
- 'hanchan_count', 'dirty')
+ 'hanchan_count', 'dirty')
class LadderRankingAdmin(admin.ModelAdmin):
actions = [recalculate]
list_display = ('placement', 'season', 'user', 'avg_placement',
- 'avg_score', 'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty')
+ 'avg_score', 'hanchan_count', 'good_hanchans',
+ 'won_hanchans', 'dirty')
list_display_links = ('user',)
list_filter = ('season',)
diff --git a/mahjong_ranking/forms.py b/mahjong_ranking/forms.py
index eadb039..4f6117e 100644
--- a/mahjong_ranking/forms.py
+++ b/mahjong_ranking/forms.py
@@ -12,7 +12,6 @@ from django.utils import timezone
from django.utils.translation import ugettext as _
from utils.html5 import forms
-
from . import models
@@ -81,7 +80,6 @@ class PlayerForm(forms.ModelForm):
class PlayerInlineFormSet(BaseInlineFormSet):
-
def clean(self):
"""Checks that no two articles have the same title."""
for form in self.forms:
@@ -102,6 +100,7 @@ class SeasonSelectForm(django.forms.Form):
season_list = season_list.values_list('season__id', 'season__name')
self.fields['season'] = django.forms.ChoiceField(choices=season_list)
+
PlayerFormSet = inlineformset_factory(
models.Hanchan,
models.Player,
diff --git a/mahjong_ranking/management/commands/random-ranking.py b/mahjong_ranking/management/commands/random-ranking.py
index 10b03e2..1bdac6f 100644
--- a/mahjong_ranking/management/commands/random-ranking.py
+++ b/mahjong_ranking/management/commands/random-ranking.py
@@ -4,13 +4,16 @@
Generate Randum Mahjong Hanchans to the the Raning System
"""
-from django.contrib import auth
-from django.core.management.base import BaseCommand
-from events.models import Event
-from mahjong_ranking import models
import random
from datetime import timedelta
+from django.contrib import auth
+from django.core.management.base import BaseCommand
+
+from events.models import Event
+from mahjong_ranking import models
+
+
class Command(BaseCommand):
help = "Deletes all expired user registrations from the database"
@@ -23,7 +26,8 @@ class Command(BaseCommand):
player_list = list()
ostwind_list = list()
for user in user_list:
- player_list.append(models.Player(user=user, hanchan=hanchan, score=25000))
+ player_list.append(
+ models.Player(user=user, hanchan=hanchan, score=25000))
for player in player_list:
player.save()
@@ -33,8 +37,8 @@ class Command(BaseCommand):
ostwind = ostwind_list.pop()
while not end_of_game:
score = random.randrange(1300, 8000, 100)
- loser = player_list[random.randrange(0,4,1)]
- winner = player_list[random.randrange(0,4,1)]
+ loser = player_list[random.randrange(0, 4, 1)]
+ winner = player_list[random.randrange(0, 4, 1)]
winner.score += score
print 'Ostwind: %s, Gewinner: %s, Verlierer: %s, %d Punkte' % (
@@ -73,9 +77,9 @@ class Command(BaseCommand):
print ""
def create_hanchan(self, event):
- start = event.start + timedelta(minutes = random.randrange(00, 300, 15))
+ start = event.start + timedelta(minutes=random.randrange(00, 300, 15))
print event.name, start
- print '='*80
+ print '=' * 80
hanchan = models.Hanchan(event=event, start=start)
hanchan.save()
self.add_players(hanchan)
@@ -87,7 +91,7 @@ class Command(BaseCommand):
self.user_list = list(auth.get_user_model().objects.all())
for event in Event.objects.all():
- for i in range(random.randrange(2,8)):
+ for i in range(random.randrange(2, 8)):
self.create_hanchan(event)
diff --git a/mahjong_ranking/middleware.py b/mahjong_ranking/middleware.py
index a921e8c..5ac5676 100644
--- a/mahjong_ranking/middleware.py
+++ b/mahjong_ranking/middleware.py
@@ -6,6 +6,7 @@ Created on 23.05.2011
"""
from django.core.cache import cache
from django.db import transaction
+
from mahjong_ranking import models
from . import logger
@@ -30,7 +31,8 @@ class DenormalizationUpdateMiddleware(object):
if len(event_ranking_queue) > 0:
while len(event_ranking_queue) > 0:
event_id, user_id = event_ranking_queue.pop()
- logger.info("recalculate %d tournament Ranking in %s", user_id, event_id)
+ 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()
@@ -57,7 +59,8 @@ class DenormalizationUpdateMiddleware(object):
user_id=user_id, season_id=season_id)[0]
ranking.recalculate()
else:
- logger.error('Season: %i; Benutzer Nr. %i - existiert nicht!', season_id, user_id)
+ logger.error('Season: %i; Benutzer Nr. %i - existiert nicht!',
+ season_id, user_id)
cache.set('ladder_ranking_queue', ladder_ranking_queue, 360)
transaction.commit()
diff --git a/mahjong_ranking/models.py b/mahjong_ranking/models.py
index 04df791..ae5b4e1 100644
--- a/mahjong_ranking/models.py
+++ b/mahjong_ranking/models.py
@@ -1,6 +1,7 @@
# -*- encoding: utf-8 -*-
from datetime import date, timedelta
+
from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import ValidationError
@@ -9,11 +10,12 @@ from django.db import models
from django.db.models.aggregates import Sum
from django.utils import timezone
from django.utils.translation import ugettext as _
-from events.models import Event
+from events.models import Event
from . import KYU_RANKS, DAN_RANKS, DAN_RANKS_DICT, MIN_HANCHANS_FOR_LADDER
from . import logger, set_dirty
+
kyu_dan_rankings = set()
ladder_rankings = set()
ladder_seasons = set()
@@ -53,8 +55,10 @@ class EventRanking(models.Model):
zur neuberrechnung zu markieren. Mittlerweile wird ein lokaler
Cache dafür verwendet, das ist schneller.
"""
- logger.info(u'Recalculate EventRanking for Player %s in %s', self.user, self.event.name) # @IgnorePep8
- event_hanchans = Player.objects.valid_hanchans(user=self.user_id, event=self.event_id) # @IgnorePep8
+ logger.info(u'Recalculate EventRanking for Player %s in %s', self.user,
+ self.event.name) # @IgnorePep8
+ event_hanchans = Player.objects.valid_hanchans(user=self.user_id,
+ event=self.event_id) # @IgnorePep8
aggregator = event_hanchans.aggregate(
models.Avg('placement'),
models.Avg('score'),
@@ -78,7 +82,9 @@ class Hanchan(models.Model):
Außerdem gehört jede Hanchan zu einer Veranstaltung.
"""
comment = models.TextField(_('Comment'), blank=True)
- confirmed = models.BooleanField(_('Has been Confirmed'), default=True, help_text=_('Only valid and confirmed Hanchans will be counted in the rating.')) # @IgnorePep8
+ confirmed = models.BooleanField(_('Has been Confirmed'), default=True,
+ help_text=_(
+ 'Only valid and confirmed Hanchans will be counted in the rating.')) # @IgnorePep8
event = models.ForeignKey(Event)
player_names = models.CharField(max_length=127, editable=False)
players = models.ManyToManyField(
@@ -86,8 +92,10 @@ class Hanchan(models.Model):
through='Player',
verbose_name=_('Players')
)
- season = models.ForeignKey('LadderSeason', blank=True, null=True, editable=False) # @IgnorePep8
- start = models.DateTimeField(_('Start'), help_text=_('This is crucial to get the right Hanchans that scores')) # @IgnorePep8
+ season = models.ForeignKey('LadderSeason', blank=True, null=True,
+ editable=False) # @IgnorePep8
+ start = models.DateTimeField(_('Start'), help_text=_(
+ 'This is crucial to get the right Hanchans that scores')) # @IgnorePep8
valid = models.BooleanField(_('Is Valid'), default=False)
class Meta(object):
@@ -96,7 +104,8 @@ class Hanchan(models.Model):
verbose_name_plural = _(u'Hanchans')
def __str__(self):
- return "Hanchan am {0:%d.%m.%Y} um {0:%H:%M} ({1})".format(self.start, self.player_names)
+ return "Hanchan am {0:%d.%m.%Y} um {0:%H:%M} ({1})".format(self.start,
+ self.player_names)
def check_validity(self):
"""
@@ -148,12 +157,14 @@ class Hanchan(models.Model):
Die Gültigkeit wird geprüft und die Sasion in der die Hanchan liegt
wird aktualisert.
"""
- logger.debug("Hanchan clean() wurde getriggert!")
+ super(Hanchan, self).clean()
# if self.pk and self.player_set.distinct().count() != 4:
- # raise ValidationError(
+ # raise ValidationError(
# _('For a Hanchan exactly 4 players are needed.'))
- if self.start and self.start > timezone.now():
+ if not self.event_id:
+ raise ValidationError(_("Hanchan has no event"))
+ elif self.start and self.start > timezone.now():
raise ValidationError(_("It's not allowed to enter future games."))
elif not (self.event.start <= self.start <= self.event.end):
raise ValidationError(_("Only games during the event are allowed"))
@@ -195,7 +206,8 @@ class Hanchan(models.Model):
def save(self, **kwargs):
logger.debug("Hanchan save() wurde getriggert!")
- self.season = self.season or LadderSeason.objects.get_by_date(self.start)
+ self.season = self.season or LadderSeason.objects.get_by_date(
+ self.start)
if self.pk:
self.check_validity()
self.compute_player_placements()
@@ -245,7 +257,8 @@ class KyuDanRanking(models.Model):
self.wins_in_a_row = 0
if self.dan and self.wins_in_a_row > 2:
- logger.info('adding bonuspoints for 3 wins in a row for %s', self.user) # @IgnorePep8
+ logger.info('adding bonuspoints for 3 wins in a row for %s',
+ self.user) # @IgnorePep8
new_dan_rank = self.dan + 1
new_dan_points = DAN_RANKS_DICT[new_dan_rank] + 1
bonus_points = new_dan_points - self.dan_points
@@ -253,7 +266,8 @@ class KyuDanRanking(models.Model):
logger.debug("Stats for %s:", self.user)
logger.debug("current dan_points: %d", self.dan_points)
logger.debug("current dan: %d", self.dan)
- logger.debug("min required points for the next dan: %d", new_dan_points) # @IgnorePep8
+ logger.debug("min required points for the next dan: %d",
+ new_dan_points) # @IgnorePep8
logger.debug("bonus points to add: %d", bonus_points)
hanchan.dan_points += bonus_points
@@ -424,7 +438,8 @@ class LadderRanking(models.Model):
return reverse('player-ladder-score', args=[self.user.username])
def recalculate(self):
- logger.info(u'Recalculate LadderRanking for Player %s in Season %s', self.user, self.season) # @IgnorePep8
+ logger.info(u'Recalculate LadderRanking for Player %s in Season %s',
+ self.user, self.season) # @IgnorePep8
ladder_hanchans = Player.objects.ladder_hanchans(
self.user_id, self.season_id)
aggregate = ladder_hanchans.aggregate(
@@ -443,7 +458,6 @@ class LadderRanking(models.Model):
class LadderSeasonManager(models.Manager):
-
def current(self):
"""
Returns the current season and caches the result for 12 hours
@@ -489,6 +503,14 @@ class LadderSeason(models.Model):
def __unicode__(self):
return self.name
+ def get_absolute_url(self):
+ """
+ URL zur Hanchanliste des Events wo diese Hanchan gelistet wurde.
+ """
+ return reverse('mahjong-ladder', kwargs={'season': self.pk})
+
+
+
def recalculate(self):
logger.info(u'Recalculate LadderSeason %s', self.name)
self.ladderranking_set.update(placement=None)
@@ -519,7 +541,8 @@ class PlayerManager(models.Manager):
queryset = queryset.filter(kyu_points__isnull=False).select_related()
return queryset
- def ladder_hanchans(self, user=None, season=None, num_hanchans=None, max_age=None): # @IgnorePep8
+ def ladder_hanchans(self, user=None, season=None, num_hanchans=None,
+ max_age=None): # @IgnorePep8
queryset = self.valid_hanchans(user).order_by('-hanchan__start')
queryset = queryset.select_related()
season = season or LadderSeason.objects.current()
@@ -593,7 +616,8 @@ class Player(models.Model):
ordering = ['-score']
def __str__(self):
- return "{0}'s Punkte vom {1: %d.%m.%Y um %H:%M}".format(self.user.username, self.hanchan.start)
+ return "{0}'s Punkte vom {1: %d.%m.%Y um %H:%M}".format(
+ self.user.username, self.hanchan.start)
def save(self, mark_dirty=True, season_id=None, *args, **kwargs):
season_id = season_id or self.hanchan.season_id
@@ -606,12 +630,15 @@ class Player(models.Model):
else:
return self
if season_id:
- logger.debug("Marking %s's season no. %i ranking for recalculation.", self.user, season_id) # @IgnorePep8
+ logger.debug(
+ "Marking %s's season no. %i ranking for recalculation.",
+ self.user, season_id) # @IgnorePep8
set_dirty(season=season_id, user=self.user_id)
logger.debug("Marking season no %i for recalculation.", season_id)
set_dirty(season=season_id)
if self.hanchan.event.is_tournament:
- logger.debug("Marking tournament %s for recalculation.", self.hanchan.event) # @IgnorePep8
+ logger.debug("Marking tournament %s for recalculation.",
+ self.hanchan.event) # @IgnorePep8
set_dirty(event=self.hanchan.event_id, user=self.user_id)
return self
@@ -622,4 +649,5 @@ def update_ranking_delete(sender, instance, **kwargs): # @UnusedVariable
if instance.season_id:
set_dirty(season=instance.season_id, user=player.user_id)
+
models.signals.pre_delete.connect(update_ranking_delete, sender=Hanchan)
diff --git a/mahjong_ranking/templates/mahjong_ranking/eventranking_list.html b/mahjong_ranking/templates/mahjong_ranking/eventranking_list.html
index 344fa9d..6632af5 100644
--- a/mahjong_ranking/templates/mahjong_ranking/eventranking_list.html
+++ b/mahjong_ranking/templates/mahjong_ranking/eventranking_list.html
@@ -1,17 +1,11 @@
-{% extends "events/event_site.html" %}
+{% extends "events/event_detail.html" %}
{% load i18n comments%}
{% block title %}{% trans "Tournament Ranking" %}: {{ event.name }}{% endblock %}
+{% block teaser %}{% trans "Tournament Ranking" %}: {{ event.name }}
{% endblock %}
-{% block event_content %}
-
-{% if event.is_tournament %}
-
-{% endif %}
+{% block maincontent %}
@@ -21,13 +15,14 @@
| {% trans "Nickname" %} |
{% trans "Name" %} |
{% trans 'Average' %} |
- Hanchans |
+ Hanchans |
- | {% trans 'Placement' %} |
- {% trans "Score" %} |
- {% trans "won" %} |
- {% trans "good" %} |
+ {% trans 'Placement' %} |
+ {% trans "Score" %} |
+ {% trans "count" %} |
+ {% trans "good" %} |
+ {% trans "won" %} |
{% for player in eventranking_list %}
@@ -42,11 +37,12 @@
{% endif %}
{{player.user}} |
- {{profile.last_name}} {{profile.first_name}} |
+ {% if user.is_authenticated %}{{profile.last_name}} {{profile.first_name}}{% else %} ---{% endif %} |
{{player.avg_placement|floatformat:2 }} |
{{player.avg_score|floatformat:0 }} |
- {{player.won_hanchans}} |
- {{player.good_hanchans}} |
+ {{player.hanchan_count}} |
+ {{player.good_hanchans}} |
+ {{player.won_hanchans}} |
{% endwith %}
{% empty %}
diff --git a/mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html b/mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html
index 72d9b05..4831404 100644
--- a/mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html
+++ b/mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html
@@ -1,10 +1,10 @@
-{% extends "base.html" %}
+{% extends "events/event_detail.html" %}
{% load i18n comments %}
{% block meta_title %}{% trans 'Delete Hanchan' %}{% endblock %}
-{% block content %}
-