From 86a0db050d01b3637939560c7feda010d80e0ef0 Mon Sep 17 00:00:00 2001 From: Christian Berg Date: Wed, 26 Nov 2014 16:04:52 +0100 Subject: [PATCH] Diverse Code Cleanups *Code wurde PEP-8 gerecht formatiert * Kleine Fehler die der PyCharm Inspector beanstandet wurden korrigiert --- .idea/kasu.iml | 4 +- aggregator/admin.py | 6 +- aggregator/feeds.py | 3 +- .../management/commands/update-feeds.py | 43 +------ aggregator/models.py | 30 ++--- aggregator/sitemaps.py | 4 +- aggregator/templatetags/aggregator.py | 3 +- content/admin.py | 17 +-- content/context_processors.py | 8 +- content/feeds.py | 12 +- content/forms.py | 12 +- content/management/commands/importarticles.py | 39 ++++--- .../management/commands/importgalleries.py | 12 +- content/models.py | 69 ++++++----- content/specs.py | 3 + .../templates/content/article_archive.html | 8 +- .../content/article_archive_month.html | 2 +- .../content/article_archive_year.html | 4 +- content/templates/content/article_detail.html | 6 +- content/templates/content/page_pdf.html | 6 +- content/templatetags/fieldset_extras.py | 8 +- content/views.py | 15 +-- events/admin.py | 10 +- events/forms.py | 23 ++-- events/models.py | 71 +++++++----- events/specs.py | 12 +- .../events/photo_confirm_delete.html | 30 ++--- events/templates/events/photo_gallery.html | 2 +- events/templates/events/photo_list.html | 2 +- events/views.py | 57 +++++---- kasu/static/admin/js/compress.py | 2 +- kasu/static/js/tiny_mce/tiny_mce_src.js | 2 +- kasu/static/js/tinymce/examples/skins.html | 2 +- kasu/utils.py | 12 +- mahjong_ranking/__init__.py | 8 +- mahjong_ranking/admin.py | 5 +- mahjong_ranking/forms.py | 14 +-- .../management/commands/random-ranking.py | 25 ++-- mahjong_ranking/middleware.py | 10 +- mahjong_ranking/models.py | 109 +++++++++++------- .../mahjong_ranking/hanchan_list.html | 2 +- .../templates/mahjong_ranking/page.html | 5 +- .../mahjong_ranking/player_dan_score.html | 8 +- .../mahjong_ranking/player_invalid_score.html | 6 +- .../mahjong_ranking/player_kyu_score.html | 8 +- .../mahjong_ranking/player_ladder_score.html | 8 +- mahjong_ranking/urls.py | 11 +- mahjong_ranking/views.py | 66 +++++------ membership/admin.py | 20 +++- membership/forms.py | 48 ++++---- .../commands/cleanup-registration.py | 6 +- membership/management/commands/get-user.py | 27 +++-- membership/models.py | 71 +++++++----- membership/specs.py | 5 +- .../templates/membership/hanchan_table.html | 2 +- membership/urls.py | 7 +- membership/views.py | 15 +-- templates/base.html | 11 +- templates/comments/form.html | 4 +- templates/registration/login.html | 4 +- .../registration/password_change_form.html | 2 +- utils/__init__.py | 4 +- utils/forms.py | 4 +- utils/html5/forms.py | 15 ++- utils/html5/models.py | 4 +- utils/html5/views.py | 4 +- utils/html5/widgets.py | 8 +- utils/html_cleaner.py | 8 +- utils/icalendar/prop.py | 8 +- utils/management/commands/compresscss.py | 8 +- utils/management/commands/compressjs.py | 8 +- utils/management/commands/scss-compiler.py | 8 +- utils/massmailer.py | 8 +- utils/middleware.py | 8 +- utils/mixins.py | 2 +- utils/templatetags/markup.py | 4 +- 76 files changed, 619 insertions(+), 528 deletions(-) diff --git a/.idea/kasu.iml b/.idea/kasu.iml index 0eebf16..570a567 100644 --- a/.idea/kasu.iml +++ b/.idea/kasu.iml @@ -3,8 +3,8 @@ - diff --git a/aggregator/admin.py b/aggregator/admin.py index 2ac726e..49b7c84 100644 --- a/aggregator/admin.py +++ b/aggregator/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin from models import Feed, FeedItem -admin.site.register(Feed, +admin.site.register( + Feed, list_display=["title", "public_url", "last_update", 'is_functional'], list_filter=["is_functional"], ordering=["title"], @@ -9,7 +10,8 @@ admin.site.register(Feed, list_per_page=500, ) -admin.site.register(FeedItem, +admin.site.register( + FeedItem, list_display=['title', 'feed', 'date_modified'], list_filter=['feed'], search_fields=['feed__title', 'feed__public_url', 'title'], diff --git a/aggregator/feeds.py b/aggregator/feeds.py index 9c2c60a..f152dd9 100644 --- a/aggregator/feeds.py +++ b/aggregator/feeds.py @@ -2,12 +2,13 @@ import django.contrib.syndication.views from .models import FeedItem +# noinspection PyMethodMayBeStatic class LatestFeedItems(django.contrib.syndication.views.Feed): link = "http://aol.animanga.at/" description = "Aktuelle Nachrichten aus der Austrian Otaku League" title = "AOL - Newsfeed" - def items(self, obj): + def items(self): return FeedItem.objects.get_recent_items() def item_title(self, item): diff --git a/aggregator/management/commands/update-feeds.py b/aggregator/management/commands/update-feeds.py index 1e61849..4760c25 100644 --- a/aggregator/management/commands/update-feeds.py +++ b/aggregator/management/commands/update-feeds.py @@ -6,53 +6,14 @@ Universal Feed Parser (http://feedparser.org) from aggregator.models import Feed from django.core.management.base import BaseCommand + class Command(BaseCommand): help = "Updates all RSS Feeds" - def parse_feed(self, feed, verbose=True): - parsed_feed = feedparser.parse(feed.feed_url) - html_parser = HTMLParser.HTMLParser() - for entry in parsed_feed: - title = entry.title.encode(parsed_feed.encoding, "xmlcharrefreplace") - guid = entry.get("id", entry.link).encode(parsed_feed.encoding, "xmlcharrefreplace") - link = entry.link.encode(parsed_feed.encoding, "xmlcharrefreplace") - if verbose: - print '>' , title - - if not guid: - guid = link - - if hasattr(entry, "summary"): - content = entry.summary - elif hasattr(entry, "content"): - content = entry.content[0].value - elif hasattr(entry, "description"): - content = entry.description - else: - content = u"" - content = content.encode(parsed_feed.encoding, "xmlcharrefreplace") - - try: - if entry.has_key('modified_parsed'): - date_modified = datetime.fromtimestamp(time.mktime(entry.modified_parsed)) - elif parsed_feed.feed.has_key('modified_parsed'): - date_modified = datetime.fromtimestamp(time.mktime(parsed_feed.feed.modified_parsed)) - elif parsed_feed.has_key('modified'): - date_modified = datetime.fromtimestamp(time.mktime(parsed_feed.modified)) - else: - date_modified = datetime.now() - except TypeError: - date_modified = datetime.now() - - try: - feed.feeditem_set.get(guid=guid) - except FeedItem.DoesNotExist: - feed.feeditem_set.create(title=title, link=link, summary=content, guid=guid, date_modified=date_modified) - def handle(self, *args, **options): verbose = int(options['verbosity']) > 0 for feed in Feed.objects.filter(is_functional=True): - if (verbose): + if verbose: print print "%s - URL: %s" % (feed.title, feed.feed_url) print '=' * 80 diff --git a/aggregator/models.py b/aggregator/models.py index 0dd1648..892a286 100644 --- a/aggregator/models.py +++ b/aggregator/models.py @@ -1,8 +1,8 @@ -''' +""" Created on 05.02.2011 @author: christian -''' +""" from datetime import datetime, timedelta from django.conf import settings @@ -14,8 +14,8 @@ import django.db.models import feedparser import urllib2 -class FeedManager(django.db.models.Manager): +class FeedManager(django.db.models.Manager): def active(self): site = settings.SITE_ID feeds = self.filter(is_functional=True, site=site) @@ -28,12 +28,13 @@ class FeedManager(django.db.models.Manager): feed.parse() return feeds -class FeedItemManager(django.db.models.Manager): +class FeedItemManager(django.db.models.Manager): def recent_items(self, max_items=10, site=None): site = site or settings.SITE_ID return self.select_related().filter(feed__site=site)[:max_items] + class Feed(models.Model): title = models.CharField(max_length=500) site = models.ForeignKey(Site) @@ -61,19 +62,22 @@ class Feed(models.Model): link = feed_entry.link guid = feed_entry.get("id", link) - summary = html_parser.unescape(feed_entry.get("summary", - feed_entry.get("description", feed_entry.get("content", u"")) - )) + summary = html_parser.unescape( + feed_entry.get("summary", feed_entry.get( + "description", + 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()) feed_item, updated = self.feed_items.get_or_create(guid=guid, - defaults={ - 'title': title, - 'link': link, - 'summary': summary, - 'date_modified': date_modified - }) + defaults={ + 'title': title, + 'link': link, + 'summary': summary, + 'date_modified': date_modified + }) feed_item.save() self.last_update = timezone.now() return self.save() diff --git a/aggregator/sitemaps.py b/aggregator/sitemaps.py index 12efd96..e8ddf2d 100644 --- a/aggregator/sitemaps.py +++ b/aggregator/sitemaps.py @@ -1,6 +1,8 @@ from django.contrib.sitemaps import Sitemap from models import FeedItem + +# noinspection PyMethodMayBeStatic class FeedItemSitemap(Sitemap): changefreq = "never" priority = 0.5 @@ -9,4 +11,4 @@ class FeedItemSitemap(Sitemap): return FeedItem.objects.get_recent_items() def lastmod(self, obj): - return obj.date_modified + return obj.date_modified diff --git a/aggregator/templatetags/aggregator.py b/aggregator/templatetags/aggregator.py index df9b812..0e7a5cd 100644 --- a/aggregator/templatetags/aggregator.py +++ b/aggregator/templatetags/aggregator.py @@ -1,5 +1,5 @@ from django import template -from aggregator.models import Feed +from models import Feed class FeedListNode(template.Node): @@ -12,6 +12,7 @@ class FeedListNode(template.Node): return '' +# noinspection PyUnusedLocal def do_get_feed_list(parser, token): """ {% get_feed_list as feed_list %} diff --git a/content/admin.py b/content/admin.py index 646fba6..4221d66 100644 --- a/content/admin.py +++ b/content/admin.py @@ -1,8 +1,8 @@ -''' +""" Created on 19.09.2011 @author: christian -''' +""" # import stuff we need from django from django.contrib import admin from . import models @@ -44,17 +44,20 @@ class PageAdmin(admin.ModelAdmin): 'classes': ('collapse', 'closed'), }), ('Meta Data', { - 'fields': ('content_type', 'slug', ('parent', 'position'), - 'status', 'template',) + 'fields': ( + 'content_type', 'slug', ('parent', 'position'), + 'status', 'template', + ) }), ) - class Media: + class Media(object): js = [ - '/static/js/tiny_mce/tiny_mce.js', - '/static/js/tinymce_setup.js', + '/static/js/tiny_mce/tiny_mce.js', + '/static/js/tinymce_setup.js', ] + admin.site.register(models.Article, ArticleAdmin) admin.site.register(models.Page, PageAdmin) admin.site.register(models.Category, CategoryAdmin) diff --git a/content/context_processors.py b/content/context_processors.py index 0726cf1..cae0058 100644 --- a/content/context_processors.py +++ b/content/context_processors.py @@ -1,9 +1,9 @@ # -*- encoding: UTF-8 -*- -''' +""" Created on 30.09.2011 @author: christian -''' +""" from . import models from django.core.cache import cache @@ -16,7 +16,7 @@ def content_menus(request): # erzeuge das Top-Level Menü top_menu_items = [] top_level_pages = cache.get('top_level_pages') - if top_level_pages == None: + if top_level_pages is None: top_level_pages = models.Page.objects.filter(parent=None) top_level_pages = top_level_pages.exclude(slug='index') top_level_pages = top_level_pages.order_by('position') @@ -31,7 +31,7 @@ def content_menus(request): # Entdecke die aktuell geöffnete Seite all_pages = cache.get('all_pages') - if all_pages == None: + if all_pages is None: all_pages = models.Page.objects.values_list('path', 'id') all_pages = dict((path, page_id) for path, page_id in all_pages) cache.set('all_pages', all_pages, 360) diff --git a/content/feeds.py b/content/feeds.py index ddbe62d..a6c2e15 100644 --- a/content/feeds.py +++ b/content/feeds.py @@ -7,13 +7,14 @@ from django.utils.feedgenerator import Rss201rev2Feed from models import Article +# noinspection PyMethodMayBeStatic class LatestNews(Feed): link = "http://www.kasu.at/" description = _("Current news from Kasu") title = "Kasu - traditonelle asiatische Spielkultur" feed_type = Rss201rev2Feed - def items(self, obj): + def items(self): return Article.objects.published()[:10] def item_title(self, item): @@ -23,7 +24,7 @@ class LatestNews(Feed): return item.author.username def item_categories(self, item): - return (item.category.name,) + return item.category.name, def item_description(self, item): return item.content @@ -32,6 +33,7 @@ class LatestNews(Feed): return datetime.combine(item.date_created, time()) +# noinspection PyMethodMayBeStatic class LatestComments(Feed): """Feed of latest comments on the current site.""" @@ -41,8 +43,10 @@ class LatestComments(Feed): feed_type = Rss201rev2Feed def items(self): - qs = comments.get_model().objects.filter(site__pk=settings.SITE_ID, - is_public=True, is_removed=False) + qs = comments.get_model().objects.filter( + site__pk=settings.SITE_ID, + is_public=True, is_removed=False + ) return qs.order_by('-submit_date')[:40] def item_author_name(self, item): diff --git a/content/forms.py b/content/forms.py index f5a70ad..157ce26 100644 --- a/content/forms.py +++ b/content/forms.py @@ -1,8 +1,8 @@ -''' +""" Created on 04.10.2011 @author: christian -''' +""" import django.forms from django.template.defaultfilters import slugify from django.utils.translation import ugettext as _ @@ -17,8 +17,12 @@ class ArticleForm(forms.ModelForm): required_css_class = 'required' class Meta(object): - fields = ('headline_de', 'content_de', 'headline_en', 'content_en', - 'category', 'image') + fields = ( + 'headline_de', 'content_de', + 'headline_en', 'content_en', + 'category', + 'image' + ) model = models.Article def save(self, force_insert=False, force_update=False, commit=True): diff --git a/content/management/commands/importarticles.py b/content/management/commands/importarticles.py index c44eb1b..ed3225b 100644 --- a/content/management/commands/importarticles.py +++ b/content/management/commands/importarticles.py @@ -1,36 +1,41 @@ # -*- coding: utf-8 -*- -from content.models import Article, Category -from django.contrib.auth.models import User +import re + +from django.contrib.auth import get_user_model from django.core.management.base import BaseCommand from django.template.defaultfilters import slugify from django.utils.datetime_safe import datetime -import re -import xlrd #@UnresolvedImport +from content.models import Article, Category +import xlrd + + +# noinspection PyPep8 class Command(BaseCommand): - help = "Importiert die alten Daten aus einer CSV Datei" #@ReservedAssignment + help = "Importiert die alten Daten aus einer CSV Datei" # @ReservedAssignment date_header_regex = r"""

(?P[\d\.]*)[\ -]*[\ -]*(?P.*)</h1>(?P<content>.*)""" header_regex = r"""<h1>[\ -]*(?P<title>.*)</h1>(?P<content>.*)""" def __init__(self): - self.author = User.objects.get(username="xeniac") + self.author = get_user_model().objects.get(username="xeniac") self.category = Category.objects.get(slug='allgemeines') - + super(Command, self).__init__() + def create_article(self): self.slug = slugify(self.headline[:50]) - article, created = Article.objects.get_or_create(slug=self.slug, date_created=self.date_created, - defaults={ - 'author': self.author, - 'headline_de': self.headline, - 'content_de': self.content, - 'category': self.category - }) + article, created = Article.objects.get_or_create(slug=self.slug, date_created=self.date_created, + defaults={ + 'author': self.author, + 'headline_de': self.headline, + 'content_de': self.content, + 'category': self.category + }) if created: - print "Created: %s - %s" % (self.date_created, self.headline) + print "Created: %s - %s" % (self.date_created, self.headline) article.clean() article.save() - + def parse_with_date(self, original): match_obj = re.search(self.date_header_regex, original, re.IGNORECASE | re.DOTALL) if match_obj: @@ -60,7 +65,7 @@ class Command(BaseCommand): except IOError: print "Datei '%s' wurde nicht gefunden! " % args[0] return False - + table = xls_file.sheet_by_index(0) for row in xrange(1, table.nrows): if not table.cell_value(row, 2) in ('Archiv', 'News'): diff --git a/content/management/commands/importgalleries.py b/content/management/commands/importgalleries.py index 1f42a09..23c2102 100644 --- a/content/management/commands/importgalleries.py +++ b/content/management/commands/importgalleries.py @@ -1,16 +1,17 @@ # -*- coding: utf-8 -*- -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model from django.core.management.base import BaseCommand from django.utils.datetime_safe import datetime from events.models import Event, Location -import xlrd # @UnresolvedImport +import xlrd class Command(BaseCommand): help = "Importiert die alten Events" # @ReservedAssignment def __init__(self): - self.author = User.objects.get(username="xeniac") + self.author = get_user_model().objects.get(username="xeniac") + super(Command, self).__init__() def handle(self, *args, **options): try: @@ -22,16 +23,15 @@ class Command(BaseCommand): table = xls_file.sheet_by_index(0) for row in xrange(1, table.nrows): - name = table.cell_value(row, 0) print name start = xlrd.xldate_as_tuple(table.cell_value(row, 1), - xls_file.datemode) + xls_file.datemode) start = datetime(start[0], start[1], start[2], 0, 0, 0) end = xlrd.xldate_as_tuple(table.cell_value(row, 2), - xls_file.datemode) + xls_file.datemode) end = datetime(end[0], end[1], end[2], 23, 59, 59) location = Location.objects.get(pk=table.cell_value(row, 3)) diff --git a/content/models.py b/content/models.py index 06d41b3..d32592c 100644 --- a/content/models.py +++ b/content/models.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- from os import path + +from django.conf import settings from django.utils.timezone import now from django.core.urlresolvers import reverse from django.core.cache import cache @@ -9,19 +11,21 @@ from django.utils.safestring import mark_safe from django.utils.translation import get_language, ugettext as _ from imagekit.models import ImageSpecField from imagekit.processors import SmartResize -from utils import STATUS_CHOICES, STATUS_WAITING, STATUS_PUBLISHED, \ - STATUS_REJECTED, cleaner, OverwriteStorage # @UnusedImport from django.core.exceptions import ValidationError +from utils import STATUS_CHOICES, STATUS_WAITING, STATUS_PUBLISHED, \ + cleaner + + CONTENT_CHOICES = ( - (0, u'Django View'), - (1, u'HTML'), - (2, u'PDF') + (0, u'Django View'), + (1, u'HTML'), + (2, u'PDF') ) def get_upload_path(instance, filename): - ''' + """ Generates the desired file path and filename for an uploaded Image. With this function Django can save the uploaded images to subfolders that also have a meaning for humans. @@ -30,7 +34,7 @@ def get_upload_path(instance, filename): @type instance: a instace of an models.Model sub-class. @param filename: The filename of the uploaded image. @type filename: String - ''' + """ extension = filename[filename.rfind('.') + 1:] if isinstance(instance, Category): return "categories/%s.%s" % (instance.slug, extension) @@ -59,11 +63,11 @@ class Article(ImageModel): content_en = models.TextField('Content', blank=True) category = models.ForeignKey('Category', verbose_name=_('Category')) image = models.ImageField(_('Image'), upload_to='news/', - blank=True, null=True) + blank=True, null=True) slug = models.SlugField(_('Slug'), unique_for_month='date_created') - author = models.ForeignKey('auth.User', verbose_name=_('Author')) + author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('Author')) status = models.SmallIntegerField(_('Status'), choices=STATUS_CHOICES, - default=STATUS_PUBLISHED) + default=STATUS_PUBLISHED) date_created = models.DateField(_('Created'), blank=True) date_modified = models.DateTimeField(_('Modified'), auto_now=True) objects = ArticleManager() @@ -117,13 +121,13 @@ class Article(ImageModel): class Page(models.Model): - ''' + """ Eine Seite auf der Homepage. Sie kann eine "statische" HTML Seite, die URL einer dynamische Django View, oder ein PDF Dokument sein. Jede Seite kann neben Deutsch auch auf Englisch angeboten werden. Ist keine englische Übersetzung vorhanden, wird die deutsche Version angeboten. - ''' + """ menu_name_de = models.CharField( 'Menü Name', max_length=255, @@ -136,26 +140,26 @@ class Page(models.Model): help_text=_('The short name for the menu-entry of this page') ) title_de = models.CharField('Titel', max_length=255, - help_text=_('This title appears in the HTML header')) + help_text=_('This title appears in the HTML header')) title_en = models.CharField('Title', max_length=255, blank=True, - help_text=_('This title appears in the HTML header')) + help_text=_('This title appears in the HTML header')) slug = models.SlugField(_('slug')) path = models.CharField(_('Path'), max_length=100, db_index=True, - editable=False, unique=True) + editable=False, unique=True) parent = models.ForeignKey('self', blank=True, null=True, - related_name='subpages', on_delete=models.SET_NULL) + related_name='subpages', on_delete=models.SET_NULL) position = models.PositiveSmallIntegerField(_('Position'), - blank=True, null=True) + blank=True, null=True) status = models.SmallIntegerField(_('status'), choices=STATUS_CHOICES, - default=STATUS_WAITING) + default=STATUS_WAITING) content_type = models.IntegerField(choices=CONTENT_CHOICES) content_de = models.TextField('Inhalt', blank=True) content_en = models.TextField('Content', blank=True) enable_comments = models.BooleanField(_('enable comments'), default=True) template = models.CharField(_('Template'), max_length=100, - default="content/page.html") + default="content/page.html") pdf_de = models.FileField(upload_to='pdf/de/', blank=True, null=True) pdf_en = models.FileField(upload_to='pdf/en/', blank=True, null=True) @@ -164,8 +168,8 @@ class Page(models.Model): @property def content(self): - return mark_safe(getattr(self, "content_%s" % get_language()) or \ - self.content_de) + cont = getattr(self, "content_%s" % get_language()) or self.content_de + return mark_safe(cont) @property def css_class(self): @@ -173,8 +177,8 @@ class Page(models.Model): @property def menu_name(self): - return getattr(self, "menu_name_%s" % get_language()) or \ - self.menu_name_de + return getattr(self, + "menu_name_%s" % get_language()) or self.menu_name_de @property def pdf_file(self): @@ -185,12 +189,12 @@ class Page(models.Model): return getattr(self, "title_%s" % get_language()) or self.title_de def clean(self): - if self.parent == None: + if self.parent is None: self.path = self.slug else: self.path = path.join(self.parent.path, self.slug) - if self.content_type == None: + if self.content_type is None: if self.pdf_de: self.content_type = 2 if self.content_de: @@ -205,14 +209,14 @@ class Page(models.Model): _(u'Please upload a PDF-File to this PDF-Page.')) def get_absolute_url(self): - path = '/' + self.path + aboslute_url = '/' + self.path if self.content_type == 1: - path += '.html' + aboslute_url += '.html' elif self.content_type == 2: - path += '.pdf' + aboslute_url += '.pdf' else: - path += '/' - return path + aboslute_url += '/' + return aboslute_url class Meta(object): ordering = ['parent__id', 'position'] @@ -227,7 +231,7 @@ class Category(ImageModel): description_de = models.TextField(_('Description')) description_en = models.TextField(_('Description'), blank=True) image = models.ImageField(_('Image'), upload_to='news/categories/', - blank=True, null=True) + blank=True, null=True) slug = models.SlugField(_('Slug'), unique=True, db_index=True) class Meta(object): @@ -242,7 +246,7 @@ class Category(ImageModel): @property def description(self): return getattr(self, "description_%s" % get_language(), - self.description_de) + self.description_de) def get_absolute_url(self): return reverse('article-archive', kwargs={'category': self.slug}) @@ -258,5 +262,6 @@ def force_cache_update(sender, instance, **kwargs): cache.delete('all_pages') cache.delete('top_level_pages') + models.signals.post_delete.connect(force_cache_update, sender=Page) models.signals.post_save.connect(force_cache_update, sender=Page) diff --git a/content/specs.py b/content/specs.py index ab70a09..2bb1fe1 100644 --- a/content/specs.py +++ b/content/specs.py @@ -1,11 +1,14 @@ from imagekit.specs import ImageSpec from imagekit import processors + +# noinspection PyPep8 class ResizeArticle(processors.Resize): width = 210 height = 130 crop = True + class Article(ImageSpec): pre_cache = True processors = [ResizeArticle] \ No newline at end of file diff --git a/content/templates/content/article_archive.html b/content/templates/content/article_archive.html index 05c0fe0..6fa80a7 100644 --- a/content/templates/content/article_archive.html +++ b/content/templates/content/article_archive.html @@ -45,11 +45,11 @@ <ul class="list" style="margin: 20px;"> {% if active_category %} {% for date in date_list %} - <li class="date"><a href="{% url "article-archive" category=active_category.slug year=date|date:'Y' %}">{{active_category.name}}: {{ date|date:'Y' }}</a></li> + <li class="date"><a href="{% url 'article-archive' category=active_category.slug year=date|date:'Y' %}">{{active_category.name}}: {{ date|date:'Y' }}</a></li> {% endfor %} {% else %} {% for date in date_list %} - <li class="date"><a href="{% url "article-archive" year=date|date:'Y' %}">{{ date|date:'Y' }}</a></li> + <li class="date"><a href="{% url 'article-archive' year=date|date:'Y' %}">{{ date|date:'Y' }}</a></li> {% endfor %} {% endif %} </ul> @@ -62,7 +62,7 @@ <article class="article"> <h3><a href="{{article.get_absolute_url}}">{{article.headline}}</a></h3> <ul class="info"> - <li><img src="{{STATIC_URL}}icons/calendar.png" alt="{% trans 'created on' %}:" title="{% trans 'created on' %}"/> <time datetime="{{article.date_created|date:"c"}}">{{ article.date_created|date }}</time></li> + <li><img src="{{STATIC_URL}}icons/calendar.png" alt="{% trans 'created on' %}:" title="{% trans 'created on' %}"/> <time datetime="{{article.date_created|date:'c'}}">{{ article.date_created|date }}</time></li> <li><img src="{{STATIC_URL}}icons/user_red.png" alt="{% trans 'by' %}:" title="{% trans 'by' %}"/> <span class="author">{{ article.author }}</span></li> <li><img src="{{STATIC_URL}}icons/comments.png" alt="{% trans 'comments' %}:" title="{% trans 'comments' %}"/> <a href="{{article.get_absolute_url}}#comments" >{{comment_count}} {% trans "comments" %}</a></li> </ul> @@ -89,6 +89,6 @@ {% block additional_buttonbar %} {% if perms.content.add_article %} - <a href="{% url "add-article" %}" class="button"><img src="{{ STATIC_URL }}icons/note_add.png" alt="" /> {% trans "Add Article" %}</a> + <a href="{% url 'add-article' %}" class="button"><img src="{{ STATIC_URL }}icons/note_add.png" alt="" /> {% trans "Add Article" %}</a> {% endif %} {% endblock %} diff --git a/content/templates/content/article_archive_month.html b/content/templates/content/article_archive_month.html index d15ed19..0b4ea35 100644 --- a/content/templates/content/article_archive_month.html +++ b/content/templates/content/article_archive_month.html @@ -4,6 +4,6 @@ {% block date_list %} <h2>{% trans "Archive" %} {{month|date:'E'}}</h2> <div class="buttonbar"> - <a href="{% url "article-archive" year=month|date:'Y' %}" class="button"><img src="{{ STATIC_URL }}icons/arrow_undo.png" alt="{% trans 'back' %}" /> {% trans 'back' %}</a> + <a href="{% url 'article-archive' year=month|date:'Y' %}" class="button"><img src="{{ STATIC_URL }}icons/arrow_undo.png" alt="{% trans 'back' %}" /> {% trans 'back' %}</a> </div> {% endblock %} diff --git a/content/templates/content/article_archive_year.html b/content/templates/content/article_archive_year.html index a8dcf1e..8209f96 100644 --- a/content/templates/content/article_archive_year.html +++ b/content/templates/content/article_archive_year.html @@ -9,11 +9,11 @@ <ul class="list" style="margin: 20px;"> {% if active_category %} {% for date in date_list %} - <li class="date"><a href="{% url "article-archive" category=active_category.slug year=year|date:'Y' month=date|date:'m' %}">{{active_category.name}}: {{ date|date:'F' }}</a></li> + <li class="date"><a href="{% url 'article-archive' category=active_category.slug year=year|date:'Y' month=date|date:'m' %}">{{active_category.name}}: {{ date|date:'F' }}</a></li> {% endfor %} {% else %} {% for date in date_list %} - <li class="date"><a href="{% url "article-archive" year=year|date:'Y' month=date|date:'m' %}">{{ date|date:'F' }}</a></li> + <li class="date"><a href="{% url 'article-archive' year=year|date:'Y' month=date|date:'m' %}">{{ date|date:'F' }}</a></li> {% endfor %} {% endif %} </ul> diff --git a/content/templates/content/article_detail.html b/content/templates/content/article_detail.html index 91d8064..8cb80c4 100644 --- a/content/templates/content/article_detail.html +++ b/content/templates/content/article_detail.html @@ -29,8 +29,8 @@ <p> </p> <ul class="info"> - <li class="user"><strong>{% trans 'Author' %}:</strong> <a href="{% url "membership-details" article.author %}" itemprop="author">{{article.author}}</a></li> - <li class="date"><strong>{% trans 'Created on' %}: </strong><time date="{{article.date_created|date:"c"}}">{{ article.date_created|date }}</time></li> + <li class="user"><strong>{% trans 'Author' %}:</strong> <a href="{% url 'membership-details' article.author %}" itemprop="author">{{article.author}}</a></li> + <li class="date"><strong>{% trans 'Created on' %}: </strong><time date="{{article.date_created|date:'c'}}">{{ article.date_created|date }}</time></li> <li class="category"><strong>{% trans "Category"%}: </strong><a href="{{ article.category.get_absolute_url }}" itemprop="articleSection">{{article.category.name}}</a></li> </ul> @@ -49,6 +49,6 @@ {% block buttonbar %} {% if perms.content.change_article %} - <a href="{% url "edit-article" article.id %}" class="button"><img src="{{STATIC_URL}}icons/note_edit.png" alt="" />{% trans "Edit Article" %}</a> + <a href="{% url 'edit-article' article.id %}" class="button"><img src="{{STATIC_URL}}icons/note_edit.png" alt="" />{% trans "Edit Article" %}</a> {% endif %} {% endblock %} \ No newline at end of file diff --git a/content/templates/content/page_pdf.html b/content/templates/content/page_pdf.html index c324357..e54269c 100644 --- a/content/templates/content/page_pdf.html +++ b/content/templates/content/page_pdf.html @@ -33,13 +33,13 @@ body { } @page { - margin-right: 0mm; - margin-bottom: 0mm; + margin-right: 0; + margin-bottom: 0; margin-top: 35mm; margin-left: 2cm; @frame header { -pdf-frame-content : page_header; - top: 0mm; + top: 0; margin: 5mm; height: 4cm; } diff --git a/content/templatetags/fieldset_extras.py b/content/templatetags/fieldset_extras.py index 9acc819..95e404c 100644 --- a/content/templatetags/fieldset_extras.py +++ b/content/templatetags/fieldset_extras.py @@ -1,11 +1,12 @@ -''' +""" Created on 10.06.2012 @author: christian -''' +""" from django import template from django.utils.datastructures import SortedDict import copy + register = template.Library() @@ -31,7 +32,7 @@ class FieldSetNode(template.Node): def get_fieldset(parser, token): try: _name_, fields, _from_, form, _as_, variable_name = \ - token.split_contents() + token.split_contents() fields = fields[1:-1] fields = [field.strip() for field in fields.split(',')] except ValueError: @@ -40,4 +41,5 @@ def get_fieldset(parser, token): ) return FieldSetNode(form, variable_name, fields) + get_fieldset = register.tag(get_fieldset) diff --git a/content/views.py b/content/views.py index 19a8e4c..57fbbdc 100644 --- a/content/views.py +++ b/content/views.py @@ -21,6 +21,7 @@ class ArticleArchiveMixin(object): return context +# noinspection PyAttributeOutsideInit class ArticleArchiveIndex(ArticleArchiveMixin, generic.ArchiveIndexView): queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED) date_field = 'date_created' @@ -83,7 +84,7 @@ class ArticleForm(PermissionRequiredMixin, generic.UpdateView): form_class = forms.ArticleForm permission_required = 'content.change_article' - def get_object(self): + def get_object(self, **kwargs): if self.kwargs.get('pk', None): return models.Article.objects.get(pk=self.kwargs['pk']) else: @@ -91,6 +92,7 @@ class ArticleForm(PermissionRequiredMixin, generic.UpdateView): class ImageList(generic.View): + # noinspection PyMethodMayBeStatic def get(self, kwargs): image_list = [] response = HttpResponse(content_type='text/javascript') @@ -137,11 +139,10 @@ class PageEditForm(PermissionRequiredMixin, generic.UpdateView): class PageHtml(generic.DetailView): - def get_object(self, queryset=None): try: return models.Page.objects.get(path=self.kwargs['path'], - content_type=1) + content_type=1) except models.Page.DoesNotExist: raise Http404( _("No Page found matching the Path %s") % self.request.path @@ -152,11 +153,10 @@ class PageHtml(generic.DetailView): class PagePdf(generic.DeleteView): - def get_object(self, queryset=None): try: return models.Page.objects.get(path=self.kwargs['path'], - content_type=2) + content_type=2) except models.Page.DoesNotExist: raise Http404( _("No PDF Document found matching the Path %s") % @@ -167,7 +167,7 @@ class PagePdf(generic.DeleteView): try: pdf_file = open(self.object.pdf_file.path, 'rb') response = HttpResponse(pdf_file.read(), - content_type='application/pdf') + content_type='application/pdf') pdf_file.close() return response except: @@ -175,7 +175,7 @@ class PagePdf(generic.DeleteView): class PageList(generic.View): - + # noinspection PyMethodMayBeStatic def get(self, kwargs): response = HttpResponse(content_type='text/javascript') response.write('var tinyMCELinkList = new Array(') @@ -213,4 +213,5 @@ class StartPage(generic.TemplateView): 'recent_comment_list': recent_comment_list, } return context + queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED) diff --git a/events/admin.py b/events/admin.py index a7ad102..c704b3e 100644 --- a/events/admin.py +++ b/events/admin.py @@ -1,8 +1,8 @@ -''' +""" Created on 19.09.2011 @author: christian -''' +""" # import stuff we need from django from django.contrib import admin from events.models import Event, Photo, Location @@ -33,11 +33,11 @@ class LocationAdmin(admin.ModelAdmin): class PhotoAdmin(admin.ModelAdmin): admin_thumbnail = AdminThumbnail(image_field='thumbnail') fields = ('image', 'event', 'name', 'description', - ('anchor_horizontal', 'anchor_vertical'), - ('photographer', 'created_date')) + ('anchor_horizontal', 'anchor_vertical'), + ('photographer', 'created_date')) list_filter = ('event', 'on_startpage',) list_display = ('admin_thumbnail', 'image', 'name', 'event', - 'photographer', 'on_startpage') + 'photographer', 'on_startpage') list_display_links = ('image',) list_editable = ('on_startpage', 'name', 'event', 'photographer') diff --git a/events/forms.py b/events/forms.py index ebc3361..e731f3d 100644 --- a/events/forms.py +++ b/events/forms.py @@ -1,24 +1,31 @@ -''' +""" Created on 03.10.2011 @author: christian -''' +""" from . import models from django import forms -from django.contrib.auth.models import User from django.utils.translation import ugettext as _ +from django.contrib.auth import get_user_model from utils.html5.widgets import DateTimeInput +user_query = get_user_model().objects.all() + class PhotoUploadForm(forms.Form): error_css_class = 'error' required_css_class = 'required' - - photographer = forms.ModelChoiceField(User.objects.all(), required=True,) + photographer = forms.ModelChoiceField(user_query, required=True,) event = forms.ModelChoiceField(models.Event.objects.all(), required=True,) - upload = forms.FileField(label=_('Images'), required=True, - widget=forms.widgets.ClearableFileInput(attrs={'multiple': 'multiple', - 'accept': "image/gif,image/png,image/jpeg"}) + upload = forms.FileField( + label=_('Images'), + required=True, + widget=forms.widgets.ClearableFileInput( + attrs={ + 'multiple': 'multiple', + 'accept': "image/gif,image/png,image/jpeg" + } + ) ) diff --git a/events/models.py b/events/models.py index 1507f31..9da20ed 100644 --- a/events/models.py +++ b/events/models.py @@ -31,7 +31,7 @@ CHOICES_VERTICAL = ( def get_upload_path(instance, filename): - ''' + """ Generates the desired file path and filename for an uploaded Image. With this function Django can save the uploaded images to subfolders that also have a meaning for humans. @@ -40,7 +40,7 @@ def get_upload_path(instance, filename): @type instance: a instace of an models.Model sub-class. @param filename: The filename of the uploaded image. @type filename: String - ''' + """ extension = filename[filename.rfind('.') + 1:] if isinstance(instance, Event): if instance.id: @@ -57,9 +57,9 @@ def get_upload_path(instance, 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) @@ -95,7 +95,7 @@ class CalloutImage(ImageSpec): class DisplayImage(ImageSpec): format = 'PNG' processors = [processors.Transpose(), - processors.ResizeToFit(width=940, height=940, upscale=False)] + processors.ResizeToFit(width=940, height=940, upscale=False)] class ThumbnailImage(CalloutImage): @@ -121,7 +121,7 @@ class ImageModel(models.Model): except AttributeError: return None if anchor_horizontal and anchor_vertical: - return (self.anchor_horizontal, self.anchor_vertical) + return self.anchor_horizontal, self.anchor_vertical else: return None @@ -130,7 +130,6 @@ class ImageModel(models.Model): class EventManager(models.Manager): - def current_event(self): try: current = self.filter(start__lte=now()) @@ -164,15 +163,15 @@ class Event(ImageModel): 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) + 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 \ + 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 \ + 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() @@ -185,7 +184,7 @@ class Event(ImageModel): def __unicode__(self): try: return "%(name)s (%(date)s)" % {'name': self.name, - 'date': self.start.date()} + 'date': self.start.date()} except: return "New Event Model" @@ -248,7 +247,7 @@ 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) + 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) @@ -283,7 +282,7 @@ class PhotoManager(models.Manager): class Photo(ImageModel): name = models.CharField(_("Name"), max_length=100, blank=True) image = models.ImageField(_("Image"), upload_to=get_upload_path, - storage=OverwriteStorage()) + storage=OverwriteStorage()) anchor_horizontal = models.FloatField( _('horizontal Anchorpoint'), choices=CHOICES_HORIZONTAL, @@ -300,14 +299,23 @@ class Photo(ImageModel): ) event = models.ForeignKey(Event) - description = models.TextField(_("Description"), max_length=300, - blank=True) - photographer = models.ForeignKey('auth.User') - on_startpage = models.BooleanField(_("Startpage"), default=False, - help_text=_('Display this Photo on the Startpage Teaser')) + description = models.TextField( + _("Description"), + max_length=300, + blank=True + ) + photographer = models.ForeignKey(settings.AUTH_USER_MODEL) + on_startpage = models.BooleanField( + _("Startpage"), + default=False, + help_text=_('Display this Photo on the Startpage Teaser') + ) created_date = models.DateTimeField(_("Published on")) - views = models.PositiveIntegerField(_("Number of views"), editable=False, - default=0) + views = models.PositiveIntegerField( + _("Number of views"), + editable=False, + default=0 + ) objects = PhotoManager() metadata = None orientation = 1 @@ -340,12 +348,12 @@ class Photo(ImageModel): self.metadata.write() def rotate(self, rotate): - ''' + """ Sets an the Exif tag in an image to set the right direction. This provides lossless image rotation. @param rotate: 'clockwise' or 'counter-clockwise' the direction in which we should rotate the image in 90° steps. - ''' + """ if not self.metadata: self.read_metadata() if rotate == 'clockwise': @@ -369,24 +377,27 @@ class Photo(ImageModel): self.save() def get_absolute_url(self): - return reverse('event-photo', kwargs={'event': self.event.id, - 'pk': self.id}) + return reverse( + 'event-photo', + kwargs={'event': self.event.id, 'pk': self.id} + ) @property def next_photo(self): - return self.get_next_by_created_date(event=self.event) + return self.get_next_by_created_date(event=self.event) @property def previous_photo(self): - return self.get_previous_by_created_date(event=self.event) + return self.get_previous_by_created_date(event=self.event) def save(self, **kwargs): - ''' + """ Triggers to save related Event to save. This should force an update for the denormalized Photo count. - ''' + """ ImageModel.save(self, **kwargs) self.save_metadata() self.event.save() + models.signals.post_save.connect(post_save_image, sender=Photo) diff --git a/events/specs.py b/events/specs.py index ff091fb..bbd0fa7 100644 --- a/events/specs.py +++ b/events/specs.py @@ -1,40 +1,48 @@ from imagekit.specs import ImageSpec from imagekit import processors + class ResizeDisplay(processors.Resize): width = 780 crop = False upscale = False -# first we define our thumbnail resize processor + +# first we define our thumbnail resize processor class ResizeCallout(processors.Resize): width = 620 height = 300 crop = True - + + class ResizeAdmin(processors.Resize): width = 60 height = 60 crop = True + class ResizeThumbnail(processors.Resize): width = 140 height = 140 crop = True + # Different Image Sizes class Admin(ImageSpec): pre_cache = False processors = [processors.Transpose, ResizeAdmin] + class Display(ImageSpec): pre_cache = False processors = [processors.Transpose, ResizeDisplay] + class Callout(ImageSpec): pre_cache = False processors = [processors.Transpose, ResizeCallout] + class Thumbnail(ImageSpec): pre_cache = False processors = [processors.Transpose, ResizeThumbnail] \ No newline at end of file diff --git a/events/templates/events/photo_confirm_delete.html b/events/templates/events/photo_confirm_delete.html index 6749545..50475f9 100644 --- a/events/templates/events/photo_confirm_delete.html +++ b/events/templates/events/photo_confirm_delete.html @@ -2,20 +2,24 @@ {% load i18n comments %} {% block maincontent %} -<header> -<form action="" method="post"> -{% csrf_token %} -<h1 class="grid_12">Dieses Photo wirklich löschen?</h1> -</header> -<img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1" /> -<br class="clear" /> -<p>Sind Sie sicher, dass Sie das Bild “{{photo.name}}” löschen wollen?</p> -<p class="buttonbar"> -<a href="{% url 'event-photo-list' photo.event.id %}" class="button" style="float: left;"><img src="{{STATIC_URL}}icons/cancel.png" alt="{% trans 'Cancel' %}" /> {% trans 'Cancel' %}</a> -<button type="submit"><img src="{{STATIC_URL}}icons/delete.png" alt="{% trans 'Delete' %}" /> {% trans 'Delete' %}</button> +<form action="" method="post" class="grid_12"> + {% csrf_token %} + <header> + <h1 class="grid_12">Dieses Photo wirklich löschen?</h1> + </header> + <p>Sind Sie sicher, dass Sie das Bild “{{photo.name}}” löschen wollen?</p> + <img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1"/> + <br class="clear"/> + <p> </p> + <p class="buttonbar"> + <a href="{% url 'event-photo-list' photo.event.id %}" class="button" style="float: left;"><img + src="{{STATIC_URL}}icons/cancel.png" alt="{% trans 'Cancel' %}"/> {% trans 'Cancel' %}</a> + <button type="submit"><img src="{{STATIC_URL}}icons/delete.png" alt="{% trans 'Delete' %}"/> + {% trans 'Delete' %} + </button> + </p> </form> -</p> - {% endblock %} +{% block buttonbar %}{% endblock %} diff --git a/events/templates/events/photo_gallery.html b/events/templates/events/photo_gallery.html index 6e0f7d8..b52e7a5 100644 --- a/events/templates/events/photo_gallery.html +++ b/events/templates/events/photo_gallery.html @@ -13,7 +13,7 @@ {% else %} <li><a href="{{ current_top_page.get_absolute_url }}" {% ifequal current_page current_top_page %}class="active"{% endifequal %}>{{current_top_page.menu_name}}</a></li> {% if perms.event.add_photo %} - <li><a href="/gallery/upload/" {% ifequal current_path 'gallery/upload' %}class="active"{% endifequal %}>{% trans 'Upload' %}</a></li> + <li><a href="/gallery/upload/" class="{% ifequal current_path 'gallery/upload' %}active{% endifequal %}">{% trans 'Upload' %}</a></li> {% endif %} {% endif %} </ul> diff --git a/events/templates/events/photo_list.html b/events/templates/events/photo_list.html index ca0f4d7..981b2a8 100644 --- a/events/templates/events/photo_list.html +++ b/events/templates/events/photo_list.html @@ -24,7 +24,7 @@ {% else %} <li><a href="{{ current_top_page.get_absolute_url }}" {% ifequal current_page current_top_page %}class="active"{% endifequal %}>{{current_top_page.menu_name}}</a></li> {% if perms.event.add_photo %} - <li><a href="/gallery/upload/" {% ifequal current_path 'gallery/upload' %}class="active"{% endifequal %}>{% trans 'Upload' %}</a></li> + <li><a href="/gallery/upload/" class="{% ifequal current_path 'gallery/upload' %}active{% endifequal %}">{% trans 'Upload' %}</a></li> {% endif %} {% endif %} </ul> diff --git a/events/views.py b/events/views.py index 308c98d..85eb3b7 100644 --- a/events/views.py +++ b/events/views.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- # Create your views here. -from . import models, forms from datetime import timedelta + from django.contrib.auth.decorators import permission_required -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model from django.core.urlresolvers import reverse from django.http import HttpResponse, Http404 from django.shortcuts import redirect @@ -13,8 +13,11 @@ 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 + class DeleteEventPhoto(generic.DeleteView): model = models.Photo @@ -22,6 +25,7 @@ class DeleteEventPhoto(generic.DeleteView): def get_object(self, queryset=None): return models.Photo.objects.get(pk=self.kwargs['pk']) """ + def get_success_url(self): return reverse('event-photo-list', args=[self.object.event.id]) @@ -29,18 +33,22 @@ class DeleteEventPhoto(generic.DeleteView): 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 - paginate_by = 5 + 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 @@ -54,6 +62,7 @@ class EventArchiveMonth(generic.MonthArchiveView): context['is_archive'] = True return context + class EventArchiveYear(generic.YearArchiveView): date_field = 'start' make_object_list = True @@ -67,24 +76,26 @@ class EventArchiveYear(generic.YearArchiveView): 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}) + 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: @@ -94,15 +105,17 @@ class EventForm(PermissionRequiredMixin, generic.UpdateView): 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) 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() @@ -130,6 +143,7 @@ class EventListIcal(generic.View): response.write(self.calendar.to_ical()) return response + class EventPhoto(generic.UpdateView): form_class = forms.EditPhotoForm model = models.Photo @@ -144,6 +158,7 @@ class EventPhoto(generic.UpdateView): else: return generic.UpdateView.post(self, request, *args, **kwargs) + class EventPhotoList(generic.ListView): context_object_name = 'photo_list' paginate_by = 36 @@ -151,7 +166,7 @@ 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): @@ -161,6 +176,7 @@ class EventPhotoList(generic.ListView): except models.Event.DoesNotExist: raise Http404(_('Event does not exist')) + class EventPhotoUpload(generic.FormView): form_class = forms.PhotoUploadForm template_name = 'events/photo_upload.html' @@ -175,24 +191,20 @@ class EventPhotoUpload(generic.FormView): return context def get_initial(self): - ''' + """ Set the current logged in user a default value for the photographer. - ''' + """ return { 'photographer': self.request.user, } def post(self, *args, **kwargs): - ''' - - ''' - self.event = models.Event.objects.get(id=self.request.REQUEST.get('event')) - photographer = self.request.POST.get('photographer') - if photographer: - photographer = User.objects.get(id=photographer) - else: - photographer = self.request.user + """ + """ + self.event = models.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 @@ -221,8 +233,9 @@ class EventPhotoUpload(generic.FormView): description = exif_data['Exif.Image.ImageDescription'].value except: description = '' - return (created_date, description) + return created_date, description + class UpcomingEvents(generic.ListView): queryset = models.Event.objects.upcoming(limit=None) - paginate_by = 12 + paginate_by = 16 diff --git a/kasu/static/admin/js/compress.py b/kasu/static/admin/js/compress.py index 8d2caa2..c91e25f 100644 --- a/kasu/static/admin/js/compress.py +++ b/kasu/static/admin/js/compress.py @@ -32,7 +32,7 @@ Compiler library and Java version 6 or later.""" for arg in args: if not arg.endswith(".js"): - arg = arg + ".js" + arg += ".js" to_compress = os.path.expanduser(arg) if os.path.exists(to_compress): to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js")) diff --git a/kasu/static/js/tiny_mce/tiny_mce_src.js b/kasu/static/js/tiny_mce/tiny_mce_src.js index 5f0d6cd..556f4f7 100644 --- a/kasu/static/js/tiny_mce/tiny_mce_src.js +++ b/kasu/static/js/tiny_mce/tiny_mce_src.js @@ -5716,5 +5716,5 @@ tinymce.html.Writer = function(settings) { // Perform a binary search for the position while (startIndex <= endIndex) { index = Math.floor((startIndex + endIndex) / 2); - + }; // Move selection to node and \ No newline at end of file diff --git a/kasu/static/js/tinymce/examples/skins.html b/kasu/static/js/tinymce/examples/skins.html index c150858..57da612 100644 --- a/kasu/static/js/tinymce/examples/skins.html +++ b/kasu/static/js/tinymce/examples/skins.html @@ -156,7 +156,7 @@ <h3>Skin support example</h3> <p> - This page displays the two skins that TinyMCE comes with. You can make your own by creating a CSS file in themes/advanced/skins/<yout skin>/ui.css + This page displays the two skins that TinyMCE comes with. You can make your own by creating a CSS file in themes/advanced/skins/>yout skin</ui.css There are more examples on how to use TinyMCE in the <a href="http://tinymce.moxiecode.com/examples/">Wiki</a>. </p> diff --git a/kasu/utils.py b/kasu/utils.py index ec29877..4dca008 100644 --- a/kasu/utils.py +++ b/kasu/utils.py @@ -1,8 +1,8 @@ -''' +""" Created on 28.09.2011 @author: christian -''' +""" from django.conf import settings from django.contrib.auth.models import User from django.contrib.sites.models import Site @@ -290,9 +290,9 @@ class MassMailer(object): html_template = None def __init__(self, subject=None, template=None, context=None): - ''' + """ - ''' + """ self.mail_queue = set() self.recipients = set() self.subject = subject @@ -357,9 +357,9 @@ class MassMailer(object): self.headers[name] = value def send(self): - ''' + """ Process the E-Mails and send them - ''' + """ self.process_mails() if len(self.mail_queue) == 0: self.log.info('No recipients for eMail "%s", bye!', self.subject) diff --git a/mahjong_ranking/__init__.py b/mahjong_ranking/__init__.py index b1288a9..62a612a 100644 --- a/mahjong_ranking/__init__.py +++ b/mahjong_ranking/__init__.py @@ -47,7 +47,7 @@ def set_dirty(event=None, season=None, user=None): elif user: key_to_add = user queue_name = 'kyu_dan_ranking_queue' - - recalculation_queue = cache.get(queue_name, set()) - recalculation_queue.add(key_to_add) - cache.set(queue_name, recalculation_queue, 360) + if key_to_add and queue_name: + recalculation_queue = cache.get(queue_name, set()) + recalculation_queue.add(key_to_add) + cache.set(queue_name, recalculation_queue, 360) diff --git a/mahjong_ranking/admin.py b/mahjong_ranking/admin.py index ea4e23d..8ae22f4 100644 --- a/mahjong_ranking/admin.py +++ b/mahjong_ranking/admin.py @@ -1,10 +1,10 @@ # -*- encoding: utf-8 -*- -''' +""" Created on 19.09.2011 @author: christian -''' +""" # import stuff we need from django from django.contrib import admin from . import models, set_dirty @@ -45,7 +45,6 @@ class EventRankingAdmin(admin.ModelAdmin): list_display = ('placement', 'user', 'event', 'avg_placement', 'avg_score', 'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty') list_display_links = ('user',) - list_filter = ('event',) actions = [recalculate] diff --git a/mahjong_ranking/forms.py b/mahjong_ranking/forms.py index a636f0e..eadb039 100644 --- a/mahjong_ranking/forms.py +++ b/mahjong_ranking/forms.py @@ -1,11 +1,11 @@ # -*- encoding: utf-8 -*- -''' +""" Created on 04.10.2011 @author: christian -''' -from django.contrib.auth.models import User +""" +from django.contrib.auth import get_user_model import django.forms from django.forms.models import BaseInlineFormSet, inlineformset_factory from django.utils import timezone @@ -30,10 +30,10 @@ class HanchanForm(forms.ModelForm): } def clean_start(self): - u''' + u""" Das Datum darf nicht in der Zukunft liegen und es muss innerhalb der Dauer des Events liegen. - ''' + """ start = self.cleaned_data['start'] event = self.cleaned_data['event'] if start > timezone.now(): @@ -58,8 +58,8 @@ class HanchanAdminForm(HanchanForm): class PlayerForm(forms.ModelForm): error_css_class = 'error' required_css_class = 'required' - player_choices = User.objects.filter(groups__in=(1, 2)).distinct() - player_choices = player_choices.order_by('username') + player_choices = get_user_model().objects.filter(groups__in=(1, 2)) + player_choices = player_choices.order_by('username').distinct() user = forms.ModelChoiceField(player_choices, required=True) comment = forms.CharField( widget=forms.widgets.TextInput(attrs={'maxlength': 255}), diff --git a/mahjong_ranking/management/commands/random-ranking.py b/mahjong_ranking/management/commands/random-ranking.py index a673d8c..10b03e2 100644 --- a/mahjong_ranking/management/commands/random-ranking.py +++ b/mahjong_ranking/management/commands/random-ranking.py @@ -4,9 +4,8 @@ Generate Randum Mahjong Hanchans to the the Raning System """ -from django.contrib.auth.models import User +from django.contrib import auth from django.core.management.base import BaseCommand -from django.utils.translation import ugettext_lazy as _ from events.models import Event from mahjong_ranking import models import random @@ -14,16 +13,16 @@ from datetime import timedelta class Command(BaseCommand): help = "Deletes all expired user registrations from the database" - + def add_players(self, hanchan): user_list = set() while len(user_list) < 4: random_user = random.choice(self.user_list) user_list.add(random_user) - + player_list = list() ostwind_list = list() - for user in user_list: + for user in user_list: player_list.append(models.Player(user=user, hanchan=hanchan, score=25000)) for player in player_list: player.save() @@ -36,7 +35,7 @@ class Command(BaseCommand): score = random.randrange(1300, 8000, 100) loser = player_list[random.randrange(0,4,1)] winner = player_list[random.randrange(0,4,1)] - winner.score += score + winner.score += score print 'Ostwind: %s, Gewinner: %s, Verlierer: %s, %d Punkte' % ( ostwind.user, @@ -53,12 +52,12 @@ class Command(BaseCommand): player.score -= score / 3 else: loser.score -= score - + for player in player_list: if player.score <= 0: player.score = 0 end_of_game = True - + if winner == ostwind: print "Wind bleibt" else: @@ -81,14 +80,14 @@ class Command(BaseCommand): hanchan.save() self.add_players(hanchan) hanchan.save() - - + + def handle(self, *args, **options): num_hanchans = int(options.get('hanchans', 4)) - self.user_list = list(User.objects.all()) - + self.user_list = list(auth.get_user_model().objects.all()) + for event in Event.objects.all(): 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 9136410..a921e8c 100644 --- a/mahjong_ranking/middleware.py +++ b/mahjong_ranking/middleware.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -''' +""" Created on 23.05.2011 @author: christian -''' +""" from django.core.cache import cache from django.db import transaction from mahjong_ranking import models @@ -11,10 +11,10 @@ from . import logger class DenormalizationUpdateMiddleware(object): - ''' + """ This Class deferres the recalculation for the Otaku XP at the end of a response. - ''' + """ def process_response(self, request, response): if request.method != 'POST': @@ -57,7 +57,7 @@ class DenormalizationUpdateMiddleware(object): user_id=user_id, season_id=season_id)[0] ranking.recalculate() else: - logger.error('Season: %i; User %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 15478ad..04df791 100644 --- a/mahjong_ranking/models.py +++ b/mahjong_ranking/models.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- from datetime import date, timedelta -from django.contrib.auth.models import User +from django.conf import settings from django.core.cache import cache from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse @@ -20,12 +20,12 @@ ladder_seasons = set() class EventRanking(models.Model): - ''' + """ Event Rankings funktionieren genauso wie Season Rankings. Sie beschränken sich aber auf einen Event und werden nur dann angestossen, wenn der Event als Turnier markiert wurde. - ''' - user = models.ForeignKey(User) + """ + user = models.ForeignKey(settings.AUTH_USER_MODEL) event = models.ForeignKey(Event) placement = models.PositiveIntegerField(blank=True, null=True) avg_placement = models.FloatField(default=4) @@ -42,7 +42,7 @@ class EventRanking(models.Model): return reverse('event-ranking', args=[self.tourney_id]) def recalculate(self): - ''' + """ Berechnet die durschnittliche Platzierung und Punkte, u.v.m. neu. Diese Daten werden benötigt um die Platzierung zu erstellen. Sie @@ -52,7 +52,7 @@ class EventRanking(models.Model): Das Eigenschaft dirty ist ein altes Überbleibsel, um das Objekt 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 aggregator = event_hanchans.aggregate( @@ -72,16 +72,20 @@ class EventRanking(models.Model): class Hanchan(models.Model): - ''' + """ Ein komplette Runde Mahjong, die aus genau 4 Spielern bestehen muss. Es werden aber noch andere Tests durchgeführt, ob sie gültig ist. 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 event = models.ForeignKey(Event) player_names = models.CharField(max_length=127, editable=False) - players = models.ManyToManyField(User, through='Player',verbose_name=_('Players')) # @IgnorePep8 + players = models.ManyToManyField( + settings.AUTH_USER_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 valid = models.BooleanField(_('Is Valid'), default=False) @@ -95,14 +99,14 @@ class Hanchan(models.Model): return "Hanchan am {0:%d.%m.%Y} um {0:%H:%M} ({1})".format(self.start, self.player_names) def check_validity(self): - ''' + """ Prüft ob die Hanchan gültig ist. 4 Spieler müssen genau 100.000 Punkte erreichen, mehr sind nur erlaubt wenn midestens ein Spieler ins Minus (auf 0) geraten ist. Ansonsten wird die Hanchan als ungültig markiert aber trotzdem abgespeichert, außerdem wird die Begründung zurück gegeben, was nicht gestimmt hat. - ''' + """ logger.debug("Hanchan wird geprüft ob er valide ist...") if not self.pk: self.valid = False @@ -132,7 +136,7 @@ class Hanchan(models.Model): return 'Wir wissen nicht warum, aber das kann nicht passen...' def clean(self): - ''' + """ Prüft ob wichtige Vorrausetzungen gegeben sind und aktualisiert ein paar Zwischenspeicher, bevor gespeichert wird. @@ -143,7 +147,7 @@ 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!") # if self.pk and self.player_set.distinct().count() != 4: @@ -156,10 +160,10 @@ class Hanchan(models.Model): return self def compute_player_placements(self): - u''' + u""" Bestimmt die Platzierung eines der Spieler einer Hanchan und speichert diese beim jeweiligen Spieler ab. - ''' + """ logger.debug("Berechne die Platzierungen neu...") attending_players = self.player_set.select_related('hanchan', 'user') attending_players = attending_players.order_by('-score') @@ -182,9 +186,9 @@ class Hanchan(models.Model): player.save(season_id=self.season_id, mark_dirty=True) def get_absolute_url(self): - ''' + """ URL zur Hanchanliste des Events wo diese Hanchan gelistet wurde. - ''' + """ url = reverse('event-hanchan-list', kwargs={'event': self.event.pk}) return u'%(url)s#%(pk)d' % {'url': url, 'pk': self.pk} @@ -201,12 +205,12 @@ class Hanchan(models.Model): class KyuDanRanking(models.Model): - u''' + u""" Die Einstufung des Spieles im Kyu bzw. Dan System. Im Gegensatz zum Ladder Ranking ist das nicht Saison gebunden. daher läuft es getrennt. - ''' - user = models.OneToOneField(User) + """ + user = models.OneToOneField(settings.AUTH_USER_MODEL) dan = models.PositiveSmallIntegerField(blank=True, null=True) dan_points = models.PositiveIntegerField(default=0) kyu = models.PositiveSmallIntegerField(default=10, blank=True, null=True) @@ -229,11 +233,11 @@ class KyuDanRanking(models.Model): return u"%s - %d. Kyu" % (self.user.username, self.kyu) def append_3_in_a_row_bonuspoints(self, hanchan): - u''' + u""" Wenn der Spieler 3 Siege in folge hatte, bekommt er so viele Punkte das er einen Dan Rang aufsteigt. Dies wird als Kommentar abgespeichert, um es besser nachvollziehen zu können. - ''' + """ if self.dan and hanchan.placement == 1: self.wins_in_a_row += 1 @@ -259,12 +263,12 @@ class KyuDanRanking(models.Model): self.dan_points += bonus_points def append_tournament_bonuspoints(self, player): - ''' + """ Prüft ob es die letzte Hanchan in einem Turnier war. Wenn ja werden bei Bedarf Bonuspunkte vergeben, falls der Spieler das Turnier gewonnen hat. :param player: Ein Player Objekt - ''' + """ bonus_points = 0 current_event = player.hanchan.event if not current_event.is_tournament: @@ -300,10 +304,10 @@ class KyuDanRanking(models.Model): return reverse('player-kyu-score', args=[self.user.username]) def recalculate(self): - ''' + """ Fetches all valid Hanchans from this Player and recalculates his Kyu/Dan Ranking. - ''' + """ logger.debug("recalculating Kyu/Dan punkte for %s...", self.user) valid_hanchans = Player.objects.valid_hanchans(user=self.user_id) valid_hanchans = valid_hanchans.order_by('hanchan__start') @@ -326,10 +330,10 @@ class KyuDanRanking(models.Model): self.save(force_update=True) def update_points(self, player): - ''' + """ Berechne die Kyu bzw. Dan Punkte für ein Spiel neu. :param player: Das Player Objekt das neuberechnet werden soll. - ''' + """ player.bonus_points = 0 player.comment = "" player.dan_points = None @@ -403,7 +407,7 @@ class KyuDanRanking(models.Model): class LadderRanking(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey(settings.AUTH_USER_MODEL) season = models.ForeignKey('LadderSeason') placement = models.PositiveIntegerField(blank=True, null=True) avg_placement = models.FloatField(blank=True, null=True) @@ -441,9 +445,9 @@ class LadderRanking(models.Model): class LadderSeasonManager(models.Manager): def current(self): - ''' + """ Returns the current season and caches the result for 12 hours - ''' + """ current_season = cache.get('current_mahjong_season') if not current_season: try: @@ -456,10 +460,10 @@ class LadderSeasonManager(models.Manager): return current_season def get_by_date(self, deadline): - ''' + """ returns the season that where running on the given date. :param deadline: the date you're intrested in - ''' + """ try: season = self.filter(start__lte=deadline, end__gte=deadline) return season[0] @@ -468,9 +472,9 @@ class LadderSeasonManager(models.Manager): class LadderSeason(models.Model): - u''' + u""" Eine Saison für das Kasu interne Ladder-Ranking. - ''' + """ name = models.CharField(max_length=100) start = models.DateField() end = models.DateField() @@ -488,10 +492,13 @@ class LadderSeason(models.Model): def recalculate(self): logger.info(u'Recalculate LadderSeason %s', self.name) self.ladderranking_set.update(placement=None) + ladderrankings_for_placement = self.ladderranking_set.filter( + hanchan_count__gt=MIN_HANCHANS_FOR_LADDER + ).order_by( + 'avg_placement', '-avg_score' + ) placement = 1 - ladder_rankings = self.ladderranking_set.filter(hanchan_count__gt=MIN_HANCHANS_FOR_LADDER) # @IgnorePep8 - ladder_rankings = ladder_rankings.order_by('avg_placement', '-avg_score') # @IgnorePep8 - for ranking in ladder_rankings: + for ranking in ladderrankings_for_placement: ranking.placement = placement ranking.save(force_update=True) placement += 1 @@ -556,12 +563,28 @@ class PlayerManager(models.Manager): class Player(models.Model): hanchan = models.ForeignKey(Hanchan) - user = models.ForeignKey(User) + user = models.ForeignKey(settings.AUTH_USER_MODEL) score = models.PositiveIntegerField(default=0) - placement = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 - kyu_points = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 - dan_points = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 - bonus_points = models.PositiveSmallIntegerField(blank=True, null=True, default=0) # @IgnorePep8 + placement = models.PositiveSmallIntegerField( + blank=True, + null=True, + default=None + ) + kyu_points = models.PositiveSmallIntegerField( + blank=True, + null=True, + default=None + ) + dan_points = models.PositiveSmallIntegerField( + blank=True, + null=True, + default=None + ) + bonus_points = models.PositiveSmallIntegerField( + blank=True, + null=True, + default=0 + ) comment = models.TextField(_('Comment'), blank=True) objects = PlayerManager() diff --git a/mahjong_ranking/templates/mahjong_ranking/hanchan_list.html b/mahjong_ranking/templates/mahjong_ranking/hanchan_list.html index 79a6de2..cd8c674 100644 --- a/mahjong_ranking/templates/mahjong_ranking/hanchan_list.html +++ b/mahjong_ranking/templates/mahjong_ranking/hanchan_list.html @@ -18,7 +18,7 @@ {% for player in hanchan.player_set.all %} <div class="player" > <a href="{% url 'player-ladder-score' player.user %}"><img - {% if player.user.get_profile.thumbnail %}src="{{player.user.get_profile.thumbnail.url}}"{% else %}src="{{STATIC_URL}}img/unknown_thumbnail.png"{% endif %} + src="{% if player.user.get_profile.thumbnail %}{{player.user.get_profile.thumbnail.url}}{% else %}{{STATIC_URL}}img/unknown_thumbnail.png{% endif %}" class="avatar" alt="" title="{% if player.dan_points != None %}Dan P.: {{player.dan_points}}{% else %}Kyu P.: {{player.kyu_points}}{% endif %} - {{player.comment}}"/></a> <h4>{{player.placement}}. - <a href="{% url 'player-ladder-score' player.user %}">{{ player.user }}</a></h4> diff --git a/mahjong_ranking/templates/mahjong_ranking/page.html b/mahjong_ranking/templates/mahjong_ranking/page.html index 84a3949..5b1d811 100644 --- a/mahjong_ranking/templates/mahjong_ranking/page.html +++ b/mahjong_ranking/templates/mahjong_ranking/page.html @@ -2,9 +2,8 @@ {% load i18n %} {% block additional_nav_elements %} - <a href="{% url 'season_ranking-archive' %}" {% if is_archive %}class="active"{% endif %}>{% trans 'Archive' %}</a> + <a href="{% url 'season_ranking-archive' %}" class="{% if is_archive %}active{% endif %}">{% trans 'Archive' %}</a> {% if perms.events.add_event %} - <a href="{% url 'event-form' %}" {% ifequal request.path '/events/add/' %}class="active"{% endifequal %}>{% trans 'Add Event' %}</a> + <a href="{% url 'event-form' %}" class="{% ifequal request.path '/events/add/' %}active{% endifequal %}">{% trans 'Add Event' %}</a> {% endif %} -</ul> {% endblock %} \ No newline at end of file diff --git a/mahjong_ranking/templates/mahjong_ranking/player_dan_score.html b/mahjong_ranking/templates/mahjong_ranking/player_dan_score.html index cd0f4c2..e98455e 100644 --- a/mahjong_ranking/templates/mahjong_ranking/player_dan_score.html +++ b/mahjong_ranking/templates/mahjong_ranking/player_dan_score.html @@ -18,7 +18,7 @@ <tr> <th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Event' %}</th> - <th rowspan="2">{% trans 'Start' %}<//th> + <th rowspan="2">{% trans 'Start' %}</th> <th rowspan="2">{% trans 'Placement' %}</th> <th colspan="4">{% trans 'Players' %}</th> <th rowspan="2">{% trans 'Dan Points' %}</th> @@ -28,7 +28,7 @@ <tr> <th>1.</th> <th>2.</th> - <th>3.<//th> + <th>3.</th> <th>4.</th> </tr> </thead> @@ -46,10 +46,10 @@ <td>{{ result.comment }}</td> <td> {% if perms.mahjong_ranking.delete_hanchan %} - <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/> + <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/></a> {% endif %} {% if perms.mahjong_ranking.change_hanchan %} - <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/> + <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/></a> {% endif %} </td> </tr> diff --git a/mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html b/mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html index 3846ed0..d1483f9 100644 --- a/mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html +++ b/mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html @@ -16,7 +16,7 @@ <table> <thead><tr> <th>{% trans 'Event' %}</th> - <th>{% trans 'Start' %}<//th> + <th>{% trans 'Start' %}</th> <th colspan="4">{% trans 'Players' %}</th> <th>{% trans 'Placement' %}</th> <th>{% trans 'Kyu Points' %}</th> @@ -36,10 +36,10 @@ <td>{{ result.comment }}</td> <td> {% if perms.mahjong_ranking.delete_hanchan %} - <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/> + <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/></a> {% endif %} {% if perms.mahjong_ranking.change_hanchan %} - <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/> + <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/></a> {% endif %} </td> </tr> diff --git a/mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html b/mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html index c55584e..43eb9d6 100644 --- a/mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html +++ b/mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html @@ -17,7 +17,7 @@ <tr> <th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Event' %}</th> - <th rowspan="2">{% trans 'Start' %}<//th> + <th rowspan="2">{% trans 'Start' %}</th> <th rowspan="2">{% trans 'Placement' %}</th> <th colspan="4">{% trans 'Players' %}</th> <th rowspan="2">{% trans 'Kyu Points' %}</th> @@ -26,7 +26,7 @@ <tr> <th>1.</th> <th>2.</th> - <th>3.<//th> + <th>3.</th> <th>4.</th> </tr> </thead> @@ -43,10 +43,10 @@ <td class="center">{{result.kyu_points}}</td> <td> {% if perms.mahjong_ranking.delete_hanchan %} - <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/> + <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/></a> {% endif %} {% if perms.mahjong_ranking.change_hanchan %} - <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/> + <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/></a> {% endif %} </td> </tr> diff --git a/mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html b/mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html index 1a241e4..ccb20c7 100644 --- a/mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html +++ b/mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html @@ -18,7 +18,7 @@ <tr> <th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Event' %}</th> - <th rowspan="2">{% trans 'Start' %}<//th> + <th rowspan="2">{% trans 'Start' %}</th> <th rowspan="2">{% trans 'Placement' %}</th> <th colspan="4">{% trans 'Players' %}</th> <th rowspan="2"></th> @@ -26,7 +26,7 @@ <tr> <th>1.</th> <th>2.</th> - <th>3.<//th> + <th>3.</th> <th>4.</th> </tr> </thead> @@ -42,10 +42,10 @@ {% endfor %} <td> {% if perms.mahjong_ranking.delete_hanchan %} - <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/> + <a href="{% url 'delete-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_delete.png" alt="{% trans 'Delete' %}" title="{% trans 'Delete Hanchan' %}"/></a> {% endif %} {% if perms.mahjong_ranking.change_hanchan %} - <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/> + <a href="{% url 'edit-hanchan' result.hanchan.pk %}"><img src="{{STATIC_URL}}icons/table_edit.png" alt="{% trans 'Edit' %}" title="{% trans 'Edit Hanchan' %}"/></a> {% endif %} </td> </tr> diff --git a/mahjong_ranking/urls.py b/mahjong_ranking/urls.py index f0425b8..695f5df 100644 --- a/mahjong_ranking/urls.py +++ b/mahjong_ranking/urls.py @@ -1,17 +1,16 @@ # -*- encoding: utf-8 -*- -''' +""" Created on 03.10.2011 @author: christian -''' +""" from django.conf.urls import * # @UnusedWildImport import views -urlpatterns = patterns('', - url(r'^$', - views.LadderRankingList.as_view(), - name="mahjong-ladder"), +urlpatterns = patterns( + '', + url(r'^$', views.LadderRankingList.as_view(), name="mahjong-ladder"), url(r'archive/$', views.LadderRankingList.as_view(), kwargs={'is_archive': True}, diff --git a/mahjong_ranking/views.py b/mahjong_ranking/views.py index 49c10c7..c349799 100644 --- a/mahjong_ranking/views.py +++ b/mahjong_ranking/views.py @@ -1,18 +1,20 @@ # -*- encoding: utf-8 -*- +import urllib + from django.contrib import auth, messages from django.core.urlresolvers import reverse -from django.http import HttpResponseRedirect, Http404 +import django.forms +import django.http from django.utils.translation import gettext as _ from django.views import generic -from events.models import Event -from mahjong_ranking import forms, models -from utils.mixins import LoginRequiredMixin, PermissionRequiredMixin -import django.forms import xlwt -from django import http -import urllib + +from events.models import Event +from . import forms, models from membership.models import Membership +from utils.mixins import LoginRequiredMixin, PermissionRequiredMixin + kyu_dan_order = { '+full_name': ('user__last_name', 'user__first_name'), @@ -29,10 +31,10 @@ kyu_dan_order = { class DeleteHanchan(PermissionRequiredMixin, generic.DeleteView): - ''' + """ Fragt zuerst nach, ob die Hanchan wirklich gelöscht werden soll. Wir die Frage mit "Ja" beantwortet, wird die die Hanchan gelöscht. - ''' + """ form_class = forms.HanchanForm model = models.Hanchan permission_required = 'mahjong_ranking.delete_hanchan' @@ -44,10 +46,10 @@ class DeleteHanchan(PermissionRequiredMixin, generic.DeleteView): class HanchanForm(PermissionRequiredMixin, generic.UpdateView): - ''' + """ Ein Formular um eine neue Hanchan anzulegen, bzw. eine bestehende zu bearbeitsen - ''' + """ form_class = forms.HanchanForm model = models.Hanchan permission_required = 'mahjong_ranking.add_hanchan' @@ -60,7 +62,7 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView): else: formset.save() self.object = form.save() - return HttpResponseRedirect(self.get_success_url()) + return django.http.HttpResponseRedirect(self.get_success_url()) def form_invalid(self, form, formset): return self.render_to_response(self.get_context_data( @@ -106,10 +108,10 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView): return context def get(self, request, *args, **kwargs): - ''' + """ :param request: - ''' + """ self.object = self.get_object() form = self.get_form(self.get_form_class()) formset = self.get_formset() @@ -131,9 +133,9 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView): class EventHanchanList(generic.ListView): - ''' + """ Auflistung aller Hanchan die während der Veranstaltung gespielt wurden. - ''' + """ model = models.Hanchan def get_queryset(self): @@ -144,7 +146,7 @@ class EventHanchanList(generic.ListView): queryset = queryset.order_by('start') return queryset except models.Event.DoesNotExist: - raise Http404(_('Event does not exist')) + raise django.http.Http404(_('Event does not exist')) def get_context_data(self, **kwargs): context = generic.ListView.get_context_data(self, **kwargs) @@ -153,10 +155,10 @@ class EventHanchanList(generic.ListView): class EventRankingList(generic.ListView): - ''' + """ Anzeige des Eventrankings, daß erstellt wurde falls der Termin als internes Turnier markiert wurde. - ''' + """ model = models.EventRanking def get_queryset(self): @@ -166,7 +168,7 @@ class EventRankingList(generic.ListView): queryset = queryset.prefetch_related() return queryset except models.Event.DoesNotExist: - raise Http404(_('Event does not exist')) + raise django.http.Http404(_('Event does not exist')) def get_context_data(self, **kwargs): context = generic.ListView.get_context_data(self, **kwargs) @@ -175,10 +177,9 @@ class EventRankingList(generic.ListView): class KyuDanRankingList(generic.ListView): - ''' + """ Anzeige aller Spiele mit ihrem Kyu bzw Dan Grad. - ''' - models.KyuDanRanking + """ default_order = '-score' order_by = '' paginate_by = 25 @@ -213,7 +214,7 @@ class LadderRankingList(generic.ListView): else: self.season = models.LadderSeason.objects.current() except models.LadderSeason.DoesNotExist: - raise Http404(_('Season does not exist')) + raise django.http.Http404(_('Season does not exist')) queryset = models.LadderRanking.objects.filter(season=self.season, placement__isnull=False).select_related() return queryset @@ -238,7 +239,7 @@ class LadderRankingExcel(generic.View): def get(self, request, **kwargs): self.queryset = self.team.members.all() - response = http.HttpResponse(mimetype=u'application/msexcel') + response = django.http.HttpResponse(mimetype=u'application/msexcel') filename = urllib.quote(self.filename.encode('utf-8')) response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % filename @@ -277,12 +278,11 @@ class LadderRankingExcel(generic.View): self.set_col(sheet, current_row, 9, profile.weight or None) self.set_col(sheet, current_row, 10, profile.emergency_contact or None) self.set_col(sheet, current_row, 11, profile.emergency_phone or None) - except models.MemberProfile.DoesNotExist: + except Membership.DoesNotExist: pass current_row += 1 for column in range(0, 13): - print column, self.max_colwidth[column] sheet.col(column).width = (self.max_colwidth[column] + 1) * 256 workbook.save(response) @@ -294,10 +294,10 @@ class PlayerScore(LoginRequiredMixin, generic.ListView): def get(self, request, *args, **kwargs): try: - self.user = auth.models.User.objects.get(username=self.kwargs.get('username')) + self.user = auth.get_user_model().objects.get(username=self.kwargs.get('username')) self.membership = Membership.objects.get_or_create(user=self.user)[0] - except auth.models.User.DoesNotExist: - raise Http404(_("No user found matching the name %s") % self.kwargs.get('username')) + except auth.get_user_model().DoesNotExist: + raise django.http.Http404(_("No user found matching the name %s") % self.kwargs.get('username')) return generic.ListView.get(self, request, *args, **kwargs) def get_context_data(self, **kwargs): @@ -305,13 +305,13 @@ class PlayerScore(LoginRequiredMixin, generic.ListView): context['membership'] = self.membership try: context['kyu_dan_ranking'] = models.KyuDanRanking.objects.get(user=self.user) - except: + except models.KyuDanRanking.DoesNotExist: context['ranking'] = None try: context['ladder_ranking'] = models.LadderRanking.objects.get( user=self.user, season=models.LadderSeason.objects.current()) - except: + except models.LadderRanking.DoesNotExist: context['ladder_ranking'] = models.LadderRanking(user=self.user) return context @@ -343,10 +343,8 @@ class PlayerLadderScore(PlayerScore): def get_context_data(self, **kwargs): context = PlayerScore.get_context_data(self, **kwargs) - season_list = models.LadderRanking.objects.filter(user=self.user).select_related('user') season_list = season_list.values_list('id', 'season__name') - context['season'] = self.season context['seasons_select_form'] = forms.SeasonSelectForm(user=self.user) context['seasons_select_field'] = django.forms.ChoiceField(choices=season_list) diff --git a/membership/admin.py b/membership/admin.py index 03d0874..e36c9d8 100644 --- a/membership/admin.py +++ b/membership/admin.py @@ -1,8 +1,8 @@ -''' +""" Created on 19.09.2011 @author: christian -''' +""" # import stuff we need from django from django.contrib import admin from membership.models import Membership, ActivationRequest @@ -15,6 +15,8 @@ def activate_user(modeladmin, request, queryset): membership = Membership.objects.get(username=activation.user.username) membership.save() activation.activate() + + activate_user.short_description = _('Activate selected User') @@ -22,6 +24,8 @@ def cleanup_activation(modeladmin, request, queryset): for activation in queryset: if activation.expired: activation.user.delete() + + cleanup_activation.short_description = _("Cleanup selected Activation Requests") @@ -39,24 +43,28 @@ class MembershipAdmin(admin.ModelAdmin): ) list_editable = ('confirmed', 'paid_until',) list_display_links = ('nickname',) - fieldsets = ((None, { - 'fields': ('gender', ('first_name', 'last_name'), ('email', 'website')) + fieldsets = ( + (None, { + 'fields': ('gender', ('first_name', 'last_name'), ('email', 'website')) }), (_('Membership'), { 'classes': ('collapse',), 'fields': (('membership', 'confirmed'), 'birthday', 'telephone', - 'street_name', ('post_code', 'city')) + 'street_name', ('post_code', 'city')) }), ) ordering = ('nickname',) search_fields = ('nickname', 'first_name', 'last_name',) + + admin.site.register(Membership, MembershipAdmin) class RegistrationAdmin(admin.ModelAdmin): list_display = ('username', 'first_name', 'last_name', 'email', - 'registration_date', 'expired') + 'registration_date', 'expired') search_fields = ('user__username', 'user__first_name') actions = [cleanup_activation, activate_user] + admin.site.register(ActivationRequest, RegistrationAdmin) diff --git a/membership/forms.py b/membership/forms.py index 2fdc0fc..9ca08d1 100644 --- a/membership/forms.py +++ b/membership/forms.py @@ -1,11 +1,11 @@ -''' +""" Created on 03.10.2011 @author: Christian -''' +""" from . import models from django.conf import settings -from django.contrib.auth.models import User +from django.contrib import auth from django.contrib.sites.models import Site from django.utils.translation import ugettext_lazy as _ from utils.html5 import forms @@ -26,29 +26,25 @@ class MembershipForm(forms.ModelForm): ) def clean_birthday(self): - if self.cleaned_data['membership'] \ - and not self.cleaned_data['birthday']: + if self.cleaned_data['membership'] and not self.cleaned_data['birthday']: raise forms.ValidationError(_('For your membership, we need this. \ Please fill out this field yet.')) return self.cleaned_data['birthday'] def clean_telephone(self): - if self.cleaned_data['membership'] \ - and not self.cleaned_data['telephone']: + if self.cleaned_data['membership'] and not self.cleaned_data['telephone']: raise forms.ValidationError(_('For your membership, we need this. \ Please fill out this field yet.')) return self.cleaned_data['telephone'] def clean_street_name(self): - if self.cleaned_data['membership'] \ - and not self.cleaned_data['street_name']: + if self.cleaned_data['membership'] and not self.cleaned_data['street_name']: raise forms.ValidationError(_('For your membership, we need this. \ Please fill out this field yet.')) return self.cleaned_data['street_name'] def clean_post_code(self): - if self.cleaned_data['membership'] \ - and not self.cleaned_data['post_code']: + if self.cleaned_data['membership'] and not self.cleaned_data['post_code']: raise forms.ValidationError(_('For your membership, we need this. \ Please fill out this field yet.')) return self.cleaned_data['post_code'] @@ -71,41 +67,43 @@ class RegistrationForm(forms.ModelForm): required_css_class = 'required' first_name = forms.CharField(max_length=30, required=True, - label=_('Given Name')) + label=_('Given Name')) last_name = forms.CharField(max_length=30, required=True, - label=_('Last Name')) + label=_('Last Name')) username = forms.SlugField(required=True, max_length=30, - label=_('Username'), - help_text=_("The Username can only contain the letters from A to Z, \ + label=_('Username'), + help_text=_("The Username can only contain the letters from A to Z, \ Numbers, and the underscore. It must be at least 2 characters long, \ and cannot be longer the 30. The first character must be a letter.")) email = forms.EmailField(required=True) password1 = forms.CharField(widget=forms.PasswordInput(), - label=_('password')) + label=_('password')) password2 = forms.CharField(widget=forms.PasswordInput(), - label=_('password (again)')) + label=_('password (again)')) recaptcha = forms.ReCaptchaField() class Meta: - model = User + model = auth.get_user_model() fields = ('first_name', 'last_name', 'username', 'email',) def clean_username(self): - ''' + """ Validate that the username is not already in use. - ''' + """ try: - User.objects.get(username__iexact=self.cleaned_data['username']) - except User.DoesNotExist: + auth.get_user_model().objects.get( + username__iexact=self.cleaned_data['username'] + ) + except auth.get_user_model().DoesNotExist: return self.cleaned_data['username'] raise forms.ValidationError(_(u'This username is already taken. \ Please choose another.')) def clean_email(self): - ''' + """ Validate that the supplied email address is unique for the site. - ''' - if User.objects.filter(email__iexact=self.cleaned_data['email']): + """ + if auth.get_user_model().objects.filter(email__iexact=self.cleaned_data['email']): raise forms.ValidationError(_(u'This email address is already in \ use. Please supply a different email address.')) return self.cleaned_data['email'] diff --git a/membership/management/commands/cleanup-registration.py b/membership/management/commands/cleanup-registration.py index 6da8f1a..c22a15a 100644 --- a/membership/management/commands/cleanup-registration.py +++ b/membership/management/commands/cleanup-registration.py @@ -1,15 +1,13 @@ # -*- coding: utf-8 -*- -from django.contrib.auth.models import User from django.core.management.base import BaseCommand -from django.utils.translation import ugettext_lazy as _ from membership.models import ActivationRequest + class Command(BaseCommand): help = "Delete all expired user registrations from the database" - + def handle(self, *args, **options): - for activation in ActivationRequest.objects.expired(): activation.user.delete() diff --git a/membership/management/commands/get-user.py b/membership/management/commands/get-user.py index 798b613..c636f9d 100644 --- a/membership/management/commands/get-user.py +++ b/membership/management/commands/get-user.py @@ -8,10 +8,10 @@ It might help your debugging to know or you might want to contact the user to tell them you have fixed the problem. """ -from django.contrib.auth.models import User +from django.conf import settings +from django.contrib import auth from django.contrib.sessions.models import Session -from django.core.management.base import BaseCommand, CommandError -from django.utils.translation import ugettext_lazy as _ +from django.core.management.base import BaseCommand from optparse import make_option @@ -19,33 +19,36 @@ class Command(BaseCommand): args = '<session_key session_key ...>' help = 'If the session still exists find it and show the related User' option_list = BaseCommand.option_list + ( - make_option('--delete', + make_option( + '--delete', action='store_true', dest='delete', default=False, - help='Delete the Useraccount'), - make_option('--ban', + help='Delete the Useraccount' + ), + make_option( + '--ban', action='store_true', dest='ban', default=False, - help='Ban the Useraccount'), - ) - + help='Ban the Useraccount' + ), + ) def handle(self, *args, **options): for session_key in args: try: session = Session.objects.get(session_key=session_key) uid = session.get_decoded().get('_auth_user_id') - user = User.objects.get(pk=uid) + user = auth.get_user_model().objects.get(pk=uid) except Session.DoesNotExist: self.stderr.write('Session "%s" does not exist' % session_key) continue - except User.DoesNotExist: + except settings.AUTH_USER_MODEL.DoesNotExist: self.stderr.write('Session "%s" has no registed User' % session_key) continue if options['delete']: - self.stdout.write('deleting %s'% user.username) + self.stdout.write('deleting %s' % user.username) user.delete() elif options['ban']: self.stdout.write('banning %s' % user.username) diff --git a/membership/models.py b/membership/models.py index f485372..e12cd3a 100644 --- a/membership/models.py +++ b/membership/models.py @@ -4,7 +4,6 @@ from . import PAID_MEMBERSHIP_GROUP from datetime import timedelta from django.utils import timezone from django.conf import settings -from django.contrib.auth.models import User from django.core.exceptions import FieldError from django.core.urlresolvers import reverse from django.db import models @@ -23,29 +22,29 @@ GENDER_CHOICES = ( def get_upload_path(instance, filename): - ''' + """ Erstellt den Pfad und Dateinamen für den Upload dynmisch. @param instance: The Membership Object for the uploaded image @param filename: the filename of the uploaded image - ''' + """ extension = path.splitext(filename)[1] return 'membership/%s%s' % (instance.user.username, extension) class ActivationManager(models.Manager): - ''' + """ Manages pending user registrations - ''' + """ def activate(self, activation_key): - ''' + """ searches the pending registrations for the given activation key. Set the corresponding user to active, if the key was found and the key has not expired yet.s @param activation_key: the key found in the activation email - ''' + """ try: activation_request = self.get(activation_key=activation_key) if activation_request.expired(): @@ -61,10 +60,10 @@ class ActivationManager(models.Manager): return False def create_pending_registration(self, user): - ''' + """ creates a PendingActivation instance with an random activation key. @param user: the user that requests activation. - ''' + """ salt = str(random.random()) activation_key = hashlib.sha1(salt + user.username).hexdigest() @@ -78,12 +77,16 @@ class ActivationManager(models.Manager): class ActivationRequest(models.Model): - ''' + """ Each ActivationRequest contains an activation key and an user. The key will be send by email to the user if the user clicks on the link he can activate his in_active account. - ''' - user = models.ForeignKey(User, unique=True, verbose_name=_('user')) + """ + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + unique=True, + verbose_name=_('user') + ) activation_key = models.CharField(_('activation key'), max_length=40) objects = ActivationManager() @@ -115,6 +118,7 @@ class ActivationRequest(models.Model): return True else: return False + expired.boolean = True @property @@ -135,28 +139,26 @@ class ActivationRequest(models.Model): class MembershipManager(models.Manager): - def get(self, *args, **kwargs): - ''' + """ First try's to fetch the requested Membership Object from the Database, if the requestetd Membership does not Exists (yet) try to fetch the corresponding User, and create the Membership with the filled in Userdata. - ''' + """ try: if 'username' in kwargs: return models.Manager.get(self, - user__username=kwargs['username'] - ) + user__username=kwargs['username']) else: return models.Manager.get(self, *args, **kwargs) except FieldError: - user = User.objects.get(*args, **kwargs) + user = settings.AUTH_USER_MODEL.objects.get(*args, **kwargs) except Membership.DoesNotExist: if 'user' in kwargs: - user = User.objects.get(pk=kwargs['user'].id) + user = settings.AUTH_USER_MODEL.objects.get(pk=kwargs['user'].id) else: - user = User.objects.get(*args, **kwargs) + user = settings.AUTH_USER_MODEL.objects.get(*args, **kwargs) membership = Membership( user=user, @@ -169,7 +171,10 @@ class MembershipManager(models.Manager): class Membership(models.Model): - user = models.OneToOneField(User) + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + unique=True + ) nickname = models.SlugField(_('Nickname'), unique=True) gender = models.CharField( _("Gender"), @@ -186,39 +191,46 @@ class Membership(models.Model): blank=True, null=True ) - membership = models.BooleanField(_('Membership'), + membership = models.BooleanField( + _('Membership'), default=False, help_text=_('Yes, I confirm that I am in agreement with the statutes \ and would like to become a member.') ) birthday = models.DateField(_("Birthday Date"), blank=True, null=True) - telephone = models.CharField(_("Telephone"), + telephone = models.CharField( + _("Telephone"), max_length=30, blank=True, null=True ) - street_name = models.CharField(_("Address"), + street_name = models.CharField( + _("Address"), max_length=75, blank=True, null=True ) - post_code = models.PositiveSmallIntegerField(_("Postcode"), + post_code = models.PositiveSmallIntegerField( + _("Postcode"), blank=True, null=True ) - city = models.CharField(_("Town/City"), + city = models.CharField( + _("Town/City"), max_length=75, blank=True, null=True ) deposit = models.PositiveSmallIntegerField(default=0, editable=False) registration_date = models.DateField(auto_now_add=True, editable=False) - paid_until = models.DateField(_('Paid until'), + paid_until = models.DateField( + _('Paid until'), blank=True, null=True, editable=True ) - confirmed = models.BooleanField(_('Confirmed'), + confirmed = models.BooleanField( + _('Confirmed'), default=False, help_text=_('This person has paid the membership fee.') ) @@ -258,7 +270,8 @@ class Membership(models.Model): self.email = self.user.email def get_absolute_url(self): - return reverse('membership-details', + return reverse( + 'membership-details', kwargs={'username': self.user.username} ) diff --git a/membership/specs.py b/membership/specs.py index 034e4e2..1cb2223 100644 --- a/membership/specs.py +++ b/membership/specs.py @@ -1,21 +1,24 @@ from imagekit.specs import ImageSpec from imagekit import processors - + class ResizeThumbnail(processors.Resize): width = 60 height = 60 crop = True + class ResizeProfile(processors.Resize): width = 140 height = 140 crop = True + class Thumbnail(ImageSpec): pre_cache = True processors = (ResizeThumbnail,) + class Profile(ImageSpec): pre_cache = False processors = (ResizeProfile,) \ No newline at end of file diff --git a/membership/templates/membership/hanchan_table.html b/membership/templates/membership/hanchan_table.html index a0ad7ad..776bada 100644 --- a/membership/templates/membership/hanchan_table.html +++ b/membership/templates/membership/hanchan_table.html @@ -2,7 +2,7 @@ <table> <thead><tr> - <th>{% trans 'Start' %}<//th> + <th>{% trans 'Start' %}</th> <th>{% trans 'Event' %}</th> <th colspan="4">{% trans 'Players' %}</th> <th>{% trans 'Kyu Points' %}</th> diff --git a/membership/urls.py b/membership/urls.py index 00aa00d..9e0f7a7 100644 --- a/membership/urls.py +++ b/membership/urls.py @@ -1,14 +1,15 @@ -''' +""" Created on 03.10.2011 @author: christian -''' +""" from django.conf.urls import * # @UnusedWildImport from . import views -urlpatterns = patterns('', +urlpatterns = patterns( + '', url('', include('social.apps.django_app.urls', namespace='social')), url('', include('django.contrib.auth.urls')), url(r'^register/$', diff --git a/membership/views.py b/membership/views.py index f3ec64c..9f31219 100644 --- a/membership/views.py +++ b/membership/views.py @@ -4,16 +4,17 @@ from django.contrib import auth, messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django.views import generic + from mahjong_ranking.models import KyuDanRanking, LadderRanking, LadderSeason -import forms -import models from utils import mixins +from . import forms, models + class ActivateRegistration(generic.DetailView): - ''' + """ Activates the Registration of an User and logs him in - ''' + """ template_name = 'membership/activation_error.html' def get(self, request, **kwargs): @@ -79,7 +80,7 @@ class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView): def get_object(self, queryset=None): if self.kwargs.get('username'): - return models.Membership.objects.get(username=self.kwargs['username']) + return models.Membership.objects.get_or_create(username=self.kwargs['username'])[0] elif self.request.user.is_authenticated(): return models.Membership.objects.get(user=self.request.user) @@ -88,13 +89,13 @@ class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView): try: context['kyu_dan_ranking'] = KyuDanRanking.objects.get( user_id=self.object.user_id) - except: + except KyuDanRanking.DoesNotExist: context['kyu_dan_ranking'] = None try: context['ladder_ranking'] = LadderRanking.objects.get( user_id=self.object.user_id, season=LadderSeason.objects.current()) - except: + except LadderRanking.DoesNotExist: context['ladder_ranking'] = LadderRanking(user=self.object.user) return context diff --git a/templates/base.html b/templates/base.html index c8f1f74..5397378 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,14 @@ {% load i18n %} -<!DOCTYPE HTML> +<!doctype html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Document + + + + +> Kasu - {% block title %}{{ current_top_page.menu_name|default:"traditionelle asiatische Spielkultur"}}{% endblock %} diff --git a/templates/comments/form.html b/templates/comments/form.html index 3ccc817..d7cc28b 100644 --- a/templates/comments/form.html +++ b/templates/comments/form.html @@ -20,8 +20,8 @@ {{form.comment}}

- - + +

{% else %}