Diverse Code Cleanups

*Code wurde PEP-8 gerecht formatiert
* Kleine Fehler die der PyCharm Inspector beanstandet wurden korrigiert
This commit is contained in:
Christian Berg
2014-11-26 16:04:52 +01:00
committed by Christian Berg
parent f34281089d
commit 86a0db050d
76 changed files with 619 additions and 528 deletions

4
.idea/kasu.iml generated
View File

@@ -3,8 +3,8 @@
<component name="FacetManager"> <component name="FacetManager">
<facet type="django" name="Django"> <facet type="django" name="Django">
<configuration> <configuration>
<option name="rootFolder" value="$MODULE_DIR$/src" /> <option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="settings.py" /> <option name="settingsModule" value="kasu/settings/dev.py" />
<option name="manageScript" value="manage.py" /> <option name="manageScript" value="manage.py" />
<option name="environment" value="&lt;map/&gt;" /> <option name="environment" value="&lt;map/&gt;" />
</configuration> </configuration>

View File

@@ -1,7 +1,8 @@
from django.contrib import admin from django.contrib import admin
from models import Feed, FeedItem from models import Feed, FeedItem
admin.site.register(Feed, admin.site.register(
Feed,
list_display=["title", "public_url", "last_update", 'is_functional'], list_display=["title", "public_url", "last_update", 'is_functional'],
list_filter=["is_functional"], list_filter=["is_functional"],
ordering=["title"], ordering=["title"],
@@ -9,7 +10,8 @@ admin.site.register(Feed,
list_per_page=500, list_per_page=500,
) )
admin.site.register(FeedItem, admin.site.register(
FeedItem,
list_display=['title', 'feed', 'date_modified'], list_display=['title', 'feed', 'date_modified'],
list_filter=['feed'], list_filter=['feed'],
search_fields=['feed__title', 'feed__public_url', 'title'], search_fields=['feed__title', 'feed__public_url', 'title'],

View File

@@ -2,12 +2,13 @@ import django.contrib.syndication.views
from .models import FeedItem from .models import FeedItem
# noinspection PyMethodMayBeStatic
class LatestFeedItems(django.contrib.syndication.views.Feed): class LatestFeedItems(django.contrib.syndication.views.Feed):
link = "http://aol.animanga.at/" link = "http://aol.animanga.at/"
description = "Aktuelle Nachrichten aus der Austrian Otaku League" description = "Aktuelle Nachrichten aus der Austrian Otaku League"
title = "AOL - Newsfeed" title = "AOL - Newsfeed"
def items(self, obj): def items(self):
return FeedItem.objects.get_recent_items() return FeedItem.objects.get_recent_items()
def item_title(self, item): def item_title(self, item):

View File

@@ -6,53 +6,14 @@ Universal Feed Parser (http://feedparser.org)
from aggregator.models import Feed from aggregator.models import Feed
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
class Command(BaseCommand): class Command(BaseCommand):
help = "Updates all RSS Feeds" 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): def handle(self, *args, **options):
verbose = int(options['verbosity']) > 0 verbose = int(options['verbosity']) > 0
for feed in Feed.objects.filter(is_functional=True): for feed in Feed.objects.filter(is_functional=True):
if (verbose): if verbose:
print print
print "%s - URL: %s" % (feed.title, feed.feed_url) print "%s - URL: %s" % (feed.title, feed.feed_url)
print '=' * 80 print '=' * 80

View File

@@ -1,8 +1,8 @@
''' """
Created on 05.02.2011 Created on 05.02.2011
@author: christian @author: christian
''' """
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.conf import settings from django.conf import settings
@@ -14,8 +14,8 @@ import django.db.models
import feedparser import feedparser
import urllib2 import urllib2
class FeedManager(django.db.models.Manager):
class FeedManager(django.db.models.Manager):
def active(self): def active(self):
site = settings.SITE_ID site = settings.SITE_ID
feeds = self.filter(is_functional=True, site=site) feeds = self.filter(is_functional=True, site=site)
@@ -28,12 +28,13 @@ class FeedManager(django.db.models.Manager):
feed.parse() feed.parse()
return feeds return feeds
class FeedItemManager(django.db.models.Manager):
class FeedItemManager(django.db.models.Manager):
def recent_items(self, max_items=10, site=None): def recent_items(self, max_items=10, site=None):
site = site or settings.SITE_ID site = site or settings.SITE_ID
return self.select_related().filter(feed__site=site)[:max_items] return self.select_related().filter(feed__site=site)[:max_items]
class Feed(models.Model): class Feed(models.Model):
title = models.CharField(max_length=500) title = models.CharField(max_length=500)
site = models.ForeignKey(Site) site = models.ForeignKey(Site)
@@ -61,9 +62,12 @@ class Feed(models.Model):
link = feed_entry.link link = feed_entry.link
guid = feed_entry.get("id", link) guid = feed_entry.get("id", link)
summary = html_parser.unescape(feed_entry.get("summary", summary = html_parser.unescape(
feed_entry.get("description", feed_entry.get("content", u"")) 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 = feed_entry.get("published_parsed", parsed_feed.get("published_parsed", timezone.now))
date_modified = timezone.make_aware(datetime(*date_modified[:6]), timezone.get_current_timezone()) date_modified = timezone.make_aware(datetime(*date_modified[:6]), timezone.get_current_timezone())

View File

@@ -1,6 +1,8 @@
from django.contrib.sitemaps import Sitemap from django.contrib.sitemaps import Sitemap
from models import FeedItem from models import FeedItem
# noinspection PyMethodMayBeStatic
class FeedItemSitemap(Sitemap): class FeedItemSitemap(Sitemap):
changefreq = "never" changefreq = "never"
priority = 0.5 priority = 0.5

View File

@@ -1,5 +1,5 @@
from django import template from django import template
from aggregator.models import Feed from models import Feed
class FeedListNode(template.Node): class FeedListNode(template.Node):
@@ -12,6 +12,7 @@ class FeedListNode(template.Node):
return '' return ''
# noinspection PyUnusedLocal
def do_get_feed_list(parser, token): def do_get_feed_list(parser, token):
""" """
{% get_feed_list as feed_list %} {% get_feed_list as feed_list %}

View File

@@ -1,8 +1,8 @@
''' """
Created on 19.09.2011 Created on 19.09.2011
@author: christian @author: christian
''' """
# import stuff we need from django # import stuff we need from django
from django.contrib import admin from django.contrib import admin
from . import models from . import models
@@ -44,17 +44,20 @@ class PageAdmin(admin.ModelAdmin):
'classes': ('collapse', 'closed'), 'classes': ('collapse', 'closed'),
}), }),
('Meta Data', { ('Meta Data', {
'fields': ('content_type', 'slug', ('parent', 'position'), 'fields': (
'status', 'template',) 'content_type', 'slug', ('parent', 'position'),
'status', 'template',
)
}), }),
) )
class Media: class Media(object):
js = [ js = [
'/static/js/tiny_mce/tiny_mce.js', '/static/js/tiny_mce/tiny_mce.js',
'/static/js/tinymce_setup.js', '/static/js/tinymce_setup.js',
] ]
admin.site.register(models.Article, ArticleAdmin) admin.site.register(models.Article, ArticleAdmin)
admin.site.register(models.Page, PageAdmin) admin.site.register(models.Page, PageAdmin)
admin.site.register(models.Category, CategoryAdmin) admin.site.register(models.Category, CategoryAdmin)

View File

@@ -1,9 +1,9 @@
# -*- encoding: UTF-8 -*- # -*- encoding: UTF-8 -*-
''' """
Created on 30.09.2011 Created on 30.09.2011
@author: christian @author: christian
''' """
from . import models from . import models
from django.core.cache import cache from django.core.cache import cache
@@ -16,7 +16,7 @@ def content_menus(request):
# erzeuge das Top-Level Menü # erzeuge das Top-Level Menü
top_menu_items = [] top_menu_items = []
top_level_pages = cache.get('top_level_pages') 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 = models.Page.objects.filter(parent=None)
top_level_pages = top_level_pages.exclude(slug='index') top_level_pages = top_level_pages.exclude(slug='index')
top_level_pages = top_level_pages.order_by('position') top_level_pages = top_level_pages.order_by('position')
@@ -31,7 +31,7 @@ def content_menus(request):
# Entdecke die aktuell geöffnete Seite # Entdecke die aktuell geöffnete Seite
all_pages = cache.get('all_pages') 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 = models.Page.objects.values_list('path', 'id')
all_pages = dict((path, page_id) for path, page_id in all_pages) all_pages = dict((path, page_id) for path, page_id in all_pages)
cache.set('all_pages', all_pages, 360) cache.set('all_pages', all_pages, 360)

View File

@@ -7,13 +7,14 @@ from django.utils.feedgenerator import Rss201rev2Feed
from models import Article from models import Article
# noinspection PyMethodMayBeStatic
class LatestNews(Feed): class LatestNews(Feed):
link = "http://www.kasu.at/" link = "http://www.kasu.at/"
description = _("Current news from Kasu") description = _("Current news from Kasu")
title = "Kasu - traditonelle asiatische Spielkultur" title = "Kasu - traditonelle asiatische Spielkultur"
feed_type = Rss201rev2Feed feed_type = Rss201rev2Feed
def items(self, obj): def items(self):
return Article.objects.published()[:10] return Article.objects.published()[:10]
def item_title(self, item): def item_title(self, item):
@@ -23,7 +24,7 @@ class LatestNews(Feed):
return item.author.username return item.author.username
def item_categories(self, item): def item_categories(self, item):
return (item.category.name,) return item.category.name,
def item_description(self, item): def item_description(self, item):
return item.content return item.content
@@ -32,6 +33,7 @@ class LatestNews(Feed):
return datetime.combine(item.date_created, time()) return datetime.combine(item.date_created, time())
# noinspection PyMethodMayBeStatic
class LatestComments(Feed): class LatestComments(Feed):
"""Feed of latest comments on the current site.""" """Feed of latest comments on the current site."""
@@ -41,8 +43,10 @@ class LatestComments(Feed):
feed_type = Rss201rev2Feed feed_type = Rss201rev2Feed
def items(self): def items(self):
qs = comments.get_model().objects.filter(site__pk=settings.SITE_ID, qs = comments.get_model().objects.filter(
is_public=True, is_removed=False) site__pk=settings.SITE_ID,
is_public=True, is_removed=False
)
return qs.order_by('-submit_date')[:40] return qs.order_by('-submit_date')[:40]
def item_author_name(self, item): def item_author_name(self, item):

View File

@@ -1,8 +1,8 @@
''' """
Created on 04.10.2011 Created on 04.10.2011
@author: christian @author: christian
''' """
import django.forms import django.forms
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@@ -17,8 +17,12 @@ class ArticleForm(forms.ModelForm):
required_css_class = 'required' required_css_class = 'required'
class Meta(object): class Meta(object):
fields = ('headline_de', 'content_de', 'headline_en', 'content_en', fields = (
'category', 'image') 'headline_de', 'content_de',
'headline_en', 'content_en',
'category',
'image'
)
model = models.Article model = models.Article
def save(self, force_insert=False, force_update=False, commit=True): def save(self, force_insert=False, force_update=False, commit=True):

View File

@@ -1,21 +1,26 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from content.models import Article, Category import re
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.utils.datetime_safe import datetime 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): 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"""<h1><span class=\"small\">(?P<date>[\d\.]*)[\ -]*</span>[\ -]*(?P<title>.*)</h1>(?P<content>.*)""" date_header_regex = r"""<h1><span class=\"small\">(?P<date>[\d\.]*)[\ -]*</span>[\ -]*(?P<title>.*)</h1>(?P<content>.*)"""
header_regex = r"""<h1>[\ -]*(?P<title>.*)</h1>(?P<content>.*)""" header_regex = r"""<h1>[\ -]*(?P<title>.*)</h1>(?P<content>.*)"""
def __init__(self): 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') self.category = Category.objects.get(slug='allgemeines')
super(Command, self).__init__()
def create_article(self): def create_article(self):
self.slug = slugify(self.headline[:50]) self.slug = slugify(self.headline[:50])

View File

@@ -1,16 +1,17 @@
# -*- coding: utf-8 -*- # -*- 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.core.management.base import BaseCommand
from django.utils.datetime_safe import datetime from django.utils.datetime_safe import datetime
from events.models import Event, Location from events.models import Event, Location
import xlrd # @UnresolvedImport import xlrd
class Command(BaseCommand): class Command(BaseCommand):
help = "Importiert die alten Events" # @ReservedAssignment help = "Importiert die alten Events" # @ReservedAssignment
def __init__(self): 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): def handle(self, *args, **options):
try: try:
@@ -22,7 +23,6 @@ class Command(BaseCommand):
table = xls_file.sheet_by_index(0) table = xls_file.sheet_by_index(0)
for row in xrange(1, table.nrows): for row in xrange(1, table.nrows):
name = table.cell_value(row, 0) name = table.cell_value(row, 0)
print name print name

View File

@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from os import path from os import path
from django.conf import settings
from django.utils.timezone import now from django.utils.timezone import now
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.cache import cache from django.core.cache import cache
@@ -9,10 +11,12 @@ from django.utils.safestring import mark_safe
from django.utils.translation import get_language, ugettext as _ from django.utils.translation import get_language, ugettext as _
from imagekit.models import ImageSpecField from imagekit.models import ImageSpecField
from imagekit.processors import SmartResize 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 django.core.exceptions import ValidationError
from utils import STATUS_CHOICES, STATUS_WAITING, STATUS_PUBLISHED, \
cleaner
CONTENT_CHOICES = ( CONTENT_CHOICES = (
(0, u'Django View'), (0, u'Django View'),
(1, u'HTML'), (1, u'HTML'),
@@ -21,7 +25,7 @@ CONTENT_CHOICES = (
def get_upload_path(instance, filename): def get_upload_path(instance, filename):
''' """
Generates the desired file path and filename for an uploaded Image. Generates the desired file path and filename for an uploaded Image.
With this function Django can save the uploaded images to subfolders that With this function Django can save the uploaded images to subfolders that
also have a meaning for humans. 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. @type instance: a instace of an models.Model sub-class.
@param filename: The filename of the uploaded image. @param filename: The filename of the uploaded image.
@type filename: String @type filename: String
''' """
extension = filename[filename.rfind('.') + 1:] extension = filename[filename.rfind('.') + 1:]
if isinstance(instance, Category): if isinstance(instance, Category):
return "categories/%s.%s" % (instance.slug, extension) return "categories/%s.%s" % (instance.slug, extension)
@@ -61,7 +65,7 @@ class Article(ImageModel):
image = models.ImageField(_('Image'), upload_to='news/', image = models.ImageField(_('Image'), upload_to='news/',
blank=True, null=True) blank=True, null=True)
slug = models.SlugField(_('Slug'), unique_for_month='date_created') 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, status = models.SmallIntegerField(_('Status'), choices=STATUS_CHOICES,
default=STATUS_PUBLISHED) default=STATUS_PUBLISHED)
date_created = models.DateField(_('Created'), blank=True) date_created = models.DateField(_('Created'), blank=True)
@@ -117,13 +121,13 @@ class Article(ImageModel):
class Page(models.Model): class Page(models.Model):
''' """
Eine Seite auf der Homepage. Sie kann eine "statische" HTML Seite, Eine Seite auf der Homepage. Sie kann eine "statische" HTML Seite,
die URL einer dynamische Django View, oder ein PDF Dokument sein. die URL einer dynamische Django View, oder ein PDF Dokument sein.
Jede Seite kann neben Deutsch auch auf Englisch angeboten werden. Jede Seite kann neben Deutsch auch auf Englisch angeboten werden.
Ist keine englische Übersetzung vorhanden, wird die deutsche Version Ist keine englische Übersetzung vorhanden, wird die deutsche Version
angeboten. angeboten.
''' """
menu_name_de = models.CharField( menu_name_de = models.CharField(
'Menü Name', 'Menü Name',
max_length=255, max_length=255,
@@ -164,8 +168,8 @@ class Page(models.Model):
@property @property
def content(self): def content(self):
return mark_safe(getattr(self, "content_%s" % get_language()) or \ cont = getattr(self, "content_%s" % get_language()) or self.content_de
self.content_de) return mark_safe(cont)
@property @property
def css_class(self): def css_class(self):
@@ -173,8 +177,8 @@ class Page(models.Model):
@property @property
def menu_name(self): def menu_name(self):
return getattr(self, "menu_name_%s" % get_language()) or \ return getattr(self,
self.menu_name_de "menu_name_%s" % get_language()) or self.menu_name_de
@property @property
def pdf_file(self): def pdf_file(self):
@@ -185,12 +189,12 @@ class Page(models.Model):
return getattr(self, "title_%s" % get_language()) or self.title_de return getattr(self, "title_%s" % get_language()) or self.title_de
def clean(self): def clean(self):
if self.parent == None: if self.parent is None:
self.path = self.slug self.path = self.slug
else: else:
self.path = path.join(self.parent.path, self.slug) self.path = path.join(self.parent.path, self.slug)
if self.content_type == None: if self.content_type is None:
if self.pdf_de: if self.pdf_de:
self.content_type = 2 self.content_type = 2
if self.content_de: if self.content_de:
@@ -205,14 +209,14 @@ class Page(models.Model):
_(u'Please upload a PDF-File to this PDF-Page.')) _(u'Please upload a PDF-File to this PDF-Page.'))
def get_absolute_url(self): def get_absolute_url(self):
path = '/' + self.path aboslute_url = '/' + self.path
if self.content_type == 1: if self.content_type == 1:
path += '.html' aboslute_url += '.html'
elif self.content_type == 2: elif self.content_type == 2:
path += '.pdf' aboslute_url += '.pdf'
else: else:
path += '/' aboslute_url += '/'
return path return aboslute_url
class Meta(object): class Meta(object):
ordering = ['parent__id', 'position'] ordering = ['parent__id', 'position']
@@ -258,5 +262,6 @@ def force_cache_update(sender, instance, **kwargs):
cache.delete('all_pages') cache.delete('all_pages')
cache.delete('top_level_pages') cache.delete('top_level_pages')
models.signals.post_delete.connect(force_cache_update, sender=Page) models.signals.post_delete.connect(force_cache_update, sender=Page)
models.signals.post_save.connect(force_cache_update, sender=Page) models.signals.post_save.connect(force_cache_update, sender=Page)

View File

@@ -1,11 +1,14 @@
from imagekit.specs import ImageSpec from imagekit.specs import ImageSpec
from imagekit import processors from imagekit import processors
# noinspection PyPep8
class ResizeArticle(processors.Resize): class ResizeArticle(processors.Resize):
width = 210 width = 210
height = 130 height = 130
crop = True crop = True
class Article(ImageSpec): class Article(ImageSpec):
pre_cache = True pre_cache = True
processors = [ResizeArticle] processors = [ResizeArticle]

View File

@@ -45,11 +45,11 @@
<ul class="list" style="margin: 20px;"> <ul class="list" style="margin: 20px;">
{% if active_category %} {% if active_category %}
{% for date in date_list %} {% 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 %} {% endfor %}
{% else %} {% else %}
{% for date in date_list %} {% 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 %} {% endfor %}
{% endif %} {% endif %}
</ul> </ul>
@@ -62,7 +62,7 @@
<article class="article"> <article class="article">
<h3><a href="{{article.get_absolute_url}}">{{article.headline}}</a></h3> <h3><a href="{{article.get_absolute_url}}">{{article.headline}}</a></h3>
<ul class="info"> <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/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> <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> </ul>
@@ -89,6 +89,6 @@
{% block additional_buttonbar %} {% block additional_buttonbar %}
{% if perms.content.add_article %} {% 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 %} {% endif %}
{% endblock %} {% endblock %}

View File

@@ -4,6 +4,6 @@
{% block date_list %} {% block date_list %}
<h2>{% trans "Archive" %} {{month|date:'E'}}</h2> <h2>{% trans "Archive" %} {{month|date:'E'}}</h2>
<div class="buttonbar"> <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> </div>
{% endblock %} {% endblock %}

View File

@@ -9,11 +9,11 @@
<ul class="list" style="margin: 20px;"> <ul class="list" style="margin: 20px;">
{% if active_category %} {% if active_category %}
{% for date in date_list %} {% 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 %} {% endfor %}
{% else %} {% else %}
{% for date in date_list %} {% 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 %} {% endfor %}
{% endif %} {% endif %}
</ul> </ul>

View File

@@ -29,8 +29,8 @@
<p>&nbsp;</p> <p>&nbsp;</p>
<ul class="info"> <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="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="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> <li class="category"><strong>{% trans "Category"%}: </strong><a href="{{ article.category.get_absolute_url }}" itemprop="articleSection">{{article.category.name}}</a></li>
</ul> </ul>
@@ -49,6 +49,6 @@
{% block buttonbar %} {% block buttonbar %}
{% if perms.content.change_article %} {% 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 %} {% endif %}
{% endblock %} {% endblock %}

View File

@@ -33,13 +33,13 @@ body {
} }
@page { @page {
margin-right: 0mm; margin-right: 0;
margin-bottom: 0mm; margin-bottom: 0;
margin-top: 35mm; margin-top: 35mm;
margin-left: 2cm; margin-left: 2cm;
@frame header { @frame header {
-pdf-frame-content : page_header; -pdf-frame-content : page_header;
top: 0mm; top: 0;
margin: 5mm; margin: 5mm;
height: 4cm; height: 4cm;
} }

View File

@@ -1,11 +1,12 @@
''' """
Created on 10.06.2012 Created on 10.06.2012
@author: christian @author: christian
''' """
from django import template from django import template
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
import copy import copy
register = template.Library() register = template.Library()
@@ -40,4 +41,5 @@ def get_fieldset(parser, token):
) )
return FieldSetNode(form, variable_name, fields) return FieldSetNode(form, variable_name, fields)
get_fieldset = register.tag(get_fieldset) get_fieldset = register.tag(get_fieldset)

View File

@@ -21,6 +21,7 @@ class ArticleArchiveMixin(object):
return context return context
# noinspection PyAttributeOutsideInit
class ArticleArchiveIndex(ArticleArchiveMixin, generic.ArchiveIndexView): class ArticleArchiveIndex(ArticleArchiveMixin, generic.ArchiveIndexView):
queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED) queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED)
date_field = 'date_created' date_field = 'date_created'
@@ -83,7 +84,7 @@ class ArticleForm(PermissionRequiredMixin, generic.UpdateView):
form_class = forms.ArticleForm form_class = forms.ArticleForm
permission_required = 'content.change_article' permission_required = 'content.change_article'
def get_object(self): def get_object(self, **kwargs):
if self.kwargs.get('pk', None): if self.kwargs.get('pk', None):
return models.Article.objects.get(pk=self.kwargs['pk']) return models.Article.objects.get(pk=self.kwargs['pk'])
else: else:
@@ -91,6 +92,7 @@ class ArticleForm(PermissionRequiredMixin, generic.UpdateView):
class ImageList(generic.View): class ImageList(generic.View):
# noinspection PyMethodMayBeStatic
def get(self, kwargs): def get(self, kwargs):
image_list = [] image_list = []
response = HttpResponse(content_type='text/javascript') response = HttpResponse(content_type='text/javascript')
@@ -137,7 +139,6 @@ class PageEditForm(PermissionRequiredMixin, generic.UpdateView):
class PageHtml(generic.DetailView): class PageHtml(generic.DetailView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
try: try:
return models.Page.objects.get(path=self.kwargs['path'], return models.Page.objects.get(path=self.kwargs['path'],
@@ -152,7 +153,6 @@ class PageHtml(generic.DetailView):
class PagePdf(generic.DeleteView): class PagePdf(generic.DeleteView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
try: try:
return models.Page.objects.get(path=self.kwargs['path'], return models.Page.objects.get(path=self.kwargs['path'],
@@ -175,7 +175,7 @@ class PagePdf(generic.DeleteView):
class PageList(generic.View): class PageList(generic.View):
# noinspection PyMethodMayBeStatic
def get(self, kwargs): def get(self, kwargs):
response = HttpResponse(content_type='text/javascript') response = HttpResponse(content_type='text/javascript')
response.write('var tinyMCELinkList = new Array(') response.write('var tinyMCELinkList = new Array(')
@@ -213,4 +213,5 @@ class StartPage(generic.TemplateView):
'recent_comment_list': recent_comment_list, 'recent_comment_list': recent_comment_list,
} }
return context return context
queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED) queryset = models.Article.objects.filter(status=models.STATUS_PUBLISHED)

View File

@@ -1,8 +1,8 @@
''' """
Created on 19.09.2011 Created on 19.09.2011
@author: christian @author: christian
''' """
# import stuff we need from django # import stuff we need from django
from django.contrib import admin from django.contrib import admin
from events.models import Event, Photo, Location from events.models import Event, Photo, Location

View File

@@ -1,24 +1,31 @@
''' """
Created on 03.10.2011 Created on 03.10.2011
@author: christian @author: christian
''' """
from . import models from . import models
from django import forms from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib.auth import get_user_model
from utils.html5.widgets import DateTimeInput from utils.html5.widgets import DateTimeInput
user_query = get_user_model().objects.all()
class PhotoUploadForm(forms.Form): class PhotoUploadForm(forms.Form):
error_css_class = 'error' error_css_class = 'error'
required_css_class = 'required' required_css_class = 'required'
photographer = forms.ModelChoiceField(user_query, required=True,)
photographer = forms.ModelChoiceField(User.objects.all(), required=True,)
event = forms.ModelChoiceField(models.Event.objects.all(), required=True,) event = forms.ModelChoiceField(models.Event.objects.all(), required=True,)
upload = forms.FileField(label=_('Images'), required=True, upload = forms.FileField(
widget=forms.widgets.ClearableFileInput(attrs={'multiple': 'multiple', label=_('Images'),
'accept': "image/gif,image/png,image/jpeg"}) required=True,
widget=forms.widgets.ClearableFileInput(
attrs={
'multiple': 'multiple',
'accept': "image/gif,image/png,image/jpeg"
}
)
) )

View File

@@ -31,7 +31,7 @@ CHOICES_VERTICAL = (
def get_upload_path(instance, filename): def get_upload_path(instance, filename):
''' """
Generates the desired file path and filename for an uploaded Image. Generates the desired file path and filename for an uploaded Image.
With this function Django can save the uploaded images to subfolders that With this function Django can save the uploaded images to subfolders that
also have a meaning for humans. 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. @type instance: a instace of an models.Model sub-class.
@param filename: The filename of the uploaded image. @param filename: The filename of the uploaded image.
@type filename: String @type filename: String
''' """
extension = filename[filename.rfind('.') + 1:] extension = filename[filename.rfind('.') + 1:]
if isinstance(instance, Event): if isinstance(instance, Event):
if instance.id: 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): def post_save_image(sender, instance=None, created=False, raw=False, **kwargs):
''' """
Reganerate the images. Reganerate the images.
''' """
os.remove(instance.display.path) os.remove(instance.display.path)
os.remove(instance.callout.path) os.remove(instance.callout.path)
os.remove(instance.thumbnail.path) os.remove(instance.thumbnail.path)
@@ -121,7 +121,7 @@ class ImageModel(models.Model):
except AttributeError: except AttributeError:
return None return None
if anchor_horizontal and anchor_vertical: if anchor_horizontal and anchor_vertical:
return (self.anchor_horizontal, self.anchor_vertical) return self.anchor_horizontal, self.anchor_vertical
else: else:
return None return None
@@ -130,7 +130,6 @@ class ImageModel(models.Model):
class EventManager(models.Manager): class EventManager(models.Manager):
def current_event(self): def current_event(self):
try: try:
current = self.filter(start__lte=now()) current = self.filter(start__lte=now())
@@ -300,14 +299,23 @@ class Photo(ImageModel):
) )
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
description = models.TextField(_("Description"), max_length=300, description = models.TextField(
blank=True) _("Description"),
photographer = models.ForeignKey('auth.User') max_length=300,
on_startpage = models.BooleanField(_("Startpage"), default=False, blank=True
help_text=_('Display this Photo on the Startpage Teaser')) )
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")) created_date = models.DateTimeField(_("Published on"))
views = models.PositiveIntegerField(_("Number of views"), editable=False, views = models.PositiveIntegerField(
default=0) _("Number of views"),
editable=False,
default=0
)
objects = PhotoManager() objects = PhotoManager()
metadata = None metadata = None
orientation = 1 orientation = 1
@@ -340,12 +348,12 @@ class Photo(ImageModel):
self.metadata.write() self.metadata.write()
def rotate(self, rotate): def rotate(self, rotate):
''' """
Sets an the Exif tag in an image to set the right direction. Sets an the Exif tag in an image to set the right direction.
This provides lossless image rotation. This provides lossless image rotation.
@param rotate: 'clockwise' or 'counter-clockwise' the direction in @param rotate: 'clockwise' or 'counter-clockwise' the direction in
which we should rotate the image in 90° steps. which we should rotate the image in 90° steps.
''' """
if not self.metadata: if not self.metadata:
self.read_metadata() self.read_metadata()
if rotate == 'clockwise': if rotate == 'clockwise':
@@ -369,8 +377,10 @@ class Photo(ImageModel):
self.save() self.save()
def get_absolute_url(self): def get_absolute_url(self):
return reverse('event-photo', kwargs={'event': self.event.id, return reverse(
'pk': self.id}) 'event-photo',
kwargs={'event': self.event.id, 'pk': self.id}
)
@property @property
def next_photo(self): def next_photo(self):
@@ -381,12 +391,13 @@ class Photo(ImageModel):
return self.get_previous_by_created_date(event=self.event) return self.get_previous_by_created_date(event=self.event)
def save(self, **kwargs): def save(self, **kwargs):
''' """
Triggers to save related Event to save. This should force an update for Triggers to save related Event to save. This should force an update for
the denormalized Photo count. the denormalized Photo count.
''' """
ImageModel.save(self, **kwargs) ImageModel.save(self, **kwargs)
self.save_metadata() self.save_metadata()
self.event.save() self.event.save()
models.signals.post_save.connect(post_save_image, sender=Photo) models.signals.post_save.connect(post_save_image, sender=Photo)

View File

@@ -1,40 +1,48 @@
from imagekit.specs import ImageSpec from imagekit.specs import ImageSpec
from imagekit import processors from imagekit import processors
class ResizeDisplay(processors.Resize): class ResizeDisplay(processors.Resize):
width = 780 width = 780
crop = False crop = False
upscale = False upscale = False
# first we define our thumbnail resize processor # first we define our thumbnail resize processor
class ResizeCallout(processors.Resize): class ResizeCallout(processors.Resize):
width = 620 width = 620
height = 300 height = 300
crop = True crop = True
class ResizeAdmin(processors.Resize): class ResizeAdmin(processors.Resize):
width = 60 width = 60
height = 60 height = 60
crop = True crop = True
class ResizeThumbnail(processors.Resize): class ResizeThumbnail(processors.Resize):
width = 140 width = 140
height = 140 height = 140
crop = True crop = True
# Different Image Sizes # Different Image Sizes
class Admin(ImageSpec): class Admin(ImageSpec):
pre_cache = False pre_cache = False
processors = [processors.Transpose, ResizeAdmin] processors = [processors.Transpose, ResizeAdmin]
class Display(ImageSpec): class Display(ImageSpec):
pre_cache = False pre_cache = False
processors = [processors.Transpose, ResizeDisplay] processors = [processors.Transpose, ResizeDisplay]
class Callout(ImageSpec): class Callout(ImageSpec):
pre_cache = False pre_cache = False
processors = [processors.Transpose, ResizeCallout] processors = [processors.Transpose, ResizeCallout]
class Thumbnail(ImageSpec): class Thumbnail(ImageSpec):
pre_cache = False pre_cache = False
processors = [processors.Transpose, ResizeThumbnail] processors = [processors.Transpose, ResizeThumbnail]

View File

@@ -2,20 +2,24 @@
{% load i18n comments %} {% load i18n comments %}
{% block maincontent %} {% block maincontent %}
<header> <form action="" method="post" class="grid_12">
<form action="" method="post">
{% csrf_token %} {% csrf_token %}
<header>
<h1 class="grid_12">Dieses Photo wirklich löschen?</h1> <h1 class="grid_12">Dieses Photo wirklich löschen?</h1>
</header> </header>
<p>Sind Sie sicher, dass Sie das Bild &ldquo;{{photo.name}}&rdquo; löschen wollen?</p>
<img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1"/> <img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1"/>
<br class="clear"/> <br class="clear"/>
<p>Sind Sie sicher, dass Sie das Bild &ldquo;{{photo.name}}&rdquo; löschen wollen?</p> <p>&nbsp;</p>
<p class="buttonbar"> <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> <a href="{% url 'event-photo-list' photo.event.id %}" class="button" style="float: left;"><img
<button type="submit"><img src="{{STATIC_URL}}icons/delete.png" alt="{% trans 'Delete' %}" /> {% trans 'Delete' %}</button> src="{{STATIC_URL}}icons/cancel.png" alt="{% trans 'Cancel' %}"/> {% trans 'Cancel' %}</a>
</form> <button type="submit"><img src="{{STATIC_URL}}icons/delete.png" alt="{% trans 'Delete' %}"/>
{% trans 'Delete' %}
</button>
</p> </p>
</form>
{% endblock %} {% endblock %}
{% block buttonbar %}{% endblock %}

View File

@@ -13,7 +13,7 @@
{% else %} {% 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> <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 %} {% 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 %}
{% endif %} {% endif %}
</ul> </ul>

View File

@@ -24,7 +24,7 @@
{% else %} {% 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> <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 %} {% 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 %}
{% endif %} {% endif %}
</ul> </ul>

View File

@@ -1,9 +1,9 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
# Create your views here. # Create your views here.
from . import models, forms
from datetime import timedelta from datetime import timedelta
from django.contrib.auth.decorators import permission_required 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.core.urlresolvers import reverse
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.shortcuts import redirect from django.shortcuts import redirect
@@ -13,8 +13,11 @@ from django.utils.translation import ugettext as _
from django.views import generic from django.views import generic
from icalendar import Calendar, Event from icalendar import Calendar, Event
import pyexiv2 import pyexiv2
from utils.mixins import PermissionRequiredMixin from utils.mixins import PermissionRequiredMixin
from . import models, forms
class DeleteEventPhoto(generic.DeleteView): class DeleteEventPhoto(generic.DeleteView):
model = models.Photo model = models.Photo
@@ -22,6 +25,7 @@ class DeleteEventPhoto(generic.DeleteView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
return models.Photo.objects.get(pk=self.kwargs['pk']) return models.Photo.objects.get(pk=self.kwargs['pk'])
""" """
def get_success_url(self): def get_success_url(self):
return reverse('event-photo-list', args=[self.object.event.id]) return reverse('event-photo-list', args=[self.object.event.id])
@@ -29,18 +33,22 @@ class DeleteEventPhoto(generic.DeleteView):
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs) return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
class EventArchiveIndex(generic.ArchiveIndexView): class EventArchiveIndex(generic.ArchiveIndexView):
allow_empty = True allow_empty = True
context_object_name = 'event_list' context_object_name = 'event_list'
date_field = 'start' date_field = 'start'
model = models.Event model = models.Event
paginate_by = 5 queryset = model.objects.all()
paginate_by = 15
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = generic.ArchiveIndexView.get_context_data(self, **kwargs) context = generic.ArchiveIndexView.get_context_data(self, **kwargs)
context['is_archive'] = True context['is_archive'] = True
return context return context
class EventArchiveMonth(generic.MonthArchiveView): class EventArchiveMonth(generic.MonthArchiveView):
date_field = 'start' date_field = 'start'
make_object_list = True make_object_list = True
@@ -54,6 +62,7 @@ class EventArchiveMonth(generic.MonthArchiveView):
context['is_archive'] = True context['is_archive'] = True
return context return context
class EventArchiveYear(generic.YearArchiveView): class EventArchiveYear(generic.YearArchiveView):
date_field = 'start' date_field = 'start'
make_object_list = True make_object_list = True
@@ -67,6 +76,7 @@ class EventArchiveYear(generic.YearArchiveView):
context['is_archive'] = True context['is_archive'] = True
return context return context
class EventDetail(generic.DetailView): class EventDetail(generic.DetailView):
model = models.Event model = models.Event
@@ -75,16 +85,17 @@ class EventDetail(generic.DetailView):
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 return context
class EventForm(PermissionRequiredMixin, generic.UpdateView): class EventForm(PermissionRequiredMixin, generic.UpdateView):
form_class = forms.EventForm form_class = forms.EventForm
permission_required = 'events.add_event' permission_required = 'events.add_event'
def get_object(self, queryset=None): def get_object(self, queryset=None):
''' """
If an id has been submitted, try return the existing Event for an update, If an id has been submitted, try return the existing Event for an update,
else creates a new one. else creates a new one.
@param queryset: @param queryset:
''' """
if self.kwargs.get('pk'): if self.kwargs.get('pk'):
event = models.Event.objects.get(pk=self.kwargs['pk']) event = models.Event.objects.get(pk=self.kwargs['pk'])
if event.event_series: if event.event_series:
@@ -94,15 +105,17 @@ class EventForm(PermissionRequiredMixin, generic.UpdateView):
else: else:
return models.Event() return models.Event()
class EventGallery(generic.ListView): class EventGallery(generic.ListView):
template_name = 'events/photo_gallery.html' template_name = 'events/photo_gallery.html'
queryset = models.Event.objects.filter(start__lt=timezone.now(), photo_count__gt=0) queryset = models.Event.objects.filter(start__lt=timezone.now(), photo_count__gt=0)
paginate_by = 12 paginate_by = 12
class EventListIcal(generic.View): class EventListIcal(generic.View):
''' """
Generates an returns an iCal File with all upcoming events. Generates an returns an iCal File with all upcoming events.
''' """
def add_event(self, event): def add_event(self, event):
ics_event = Event() ics_event = Event()
@@ -130,6 +143,7 @@ class EventListIcal(generic.View):
response.write(self.calendar.to_ical()) response.write(self.calendar.to_ical())
return response return response
class EventPhoto(generic.UpdateView): class EventPhoto(generic.UpdateView):
form_class = forms.EditPhotoForm form_class = forms.EditPhotoForm
model = models.Photo model = models.Photo
@@ -144,6 +158,7 @@ class EventPhoto(generic.UpdateView):
else: else:
return generic.UpdateView.post(self, request, *args, **kwargs) return generic.UpdateView.post(self, request, *args, **kwargs)
class EventPhotoList(generic.ListView): class EventPhotoList(generic.ListView):
context_object_name = 'photo_list' context_object_name = 'photo_list'
paginate_by = 36 paginate_by = 36
@@ -161,6 +176,7 @@ class EventPhotoList(generic.ListView):
except models.Event.DoesNotExist: except models.Event.DoesNotExist:
raise Http404(_('Event does not exist')) raise Http404(_('Event does not exist'))
class EventPhotoUpload(generic.FormView): class EventPhotoUpload(generic.FormView):
form_class = forms.PhotoUploadForm form_class = forms.PhotoUploadForm
template_name = 'events/photo_upload.html' template_name = 'events/photo_upload.html'
@@ -175,24 +191,20 @@ class EventPhotoUpload(generic.FormView):
return context return context
def get_initial(self): def get_initial(self):
''' """
Set the current logged in user a default value for the photographer. Set the current logged in user a default value for the photographer.
''' """
return { return {
'photographer': self.request.user, 'photographer': self.request.user,
} }
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
''' """
''' """
self.event = models.Event.objects.get(id=self.request.REQUEST.get('event')) self.event = models.Event.objects.get(id=self.request.REQUEST.get('event'))
photographer = self.request.POST.get('photographer') photographer = self.request.POST.get('photographer', self.request.user.id)
if photographer: photographer = get_user_model().objects.get(id=photographer)
photographer = User.objects.get(id=photographer)
else:
photographer = self.request.user
self.counter = 1 self.counter = 1
for upload in self.request.FILES.getlist('upload'): for upload in self.request.FILES.getlist('upload'):
name = upload.name name = upload.name
@@ -221,8 +233,9 @@ class EventPhotoUpload(generic.FormView):
description = exif_data['Exif.Image.ImageDescription'].value description = exif_data['Exif.Image.ImageDescription'].value
except: except:
description = '' description = ''
return (created_date, description) return created_date, description
class UpcomingEvents(generic.ListView): class UpcomingEvents(generic.ListView):
queryset = models.Event.objects.upcoming(limit=None) queryset = models.Event.objects.upcoming(limit=None)
paginate_by = 12 paginate_by = 16

View File

@@ -32,7 +32,7 @@ Compiler library and Java version 6 or later."""
for arg in args: for arg in args:
if not arg.endswith(".js"): if not arg.endswith(".js"):
arg = arg + ".js" arg += ".js"
to_compress = os.path.expanduser(arg) to_compress = os.path.expanduser(arg)
if os.path.exists(to_compress): if os.path.exists(to_compress):
to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js")) to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js"))

View File

@@ -5716,5 +5716,5 @@ tinymce.html.Writer = function(settings) {
// Perform a binary search for the position // Perform a binary search for the position
while (startIndex <= endIndex) { while (startIndex <= endIndex) {
index = Math.floor((startIndex + endIndex) / 2); index = Math.floor((startIndex + endIndex) / 2);
};
// Move selection to node and // Move selection to node and

View File

@@ -156,7 +156,7 @@
<h3>Skin support example</h3> <h3>Skin support example</h3>
<p> <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/&gt;yout skin&lt;/ui.css
There are more examples on how to use TinyMCE in the <a href="http://tinymce.moxiecode.com/examples/">Wiki</a>. There are more examples on how to use TinyMCE in the <a href="http://tinymce.moxiecode.com/examples/">Wiki</a>.
</p> </p>

View File

@@ -1,8 +1,8 @@
''' """
Created on 28.09.2011 Created on 28.09.2011
@author: christian @author: christian
''' """
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
@@ -290,9 +290,9 @@ class MassMailer(object):
html_template = None html_template = None
def __init__(self, subject=None, template=None, context=None): def __init__(self, subject=None, template=None, context=None):
''' """
''' """
self.mail_queue = set() self.mail_queue = set()
self.recipients = set() self.recipients = set()
self.subject = subject self.subject = subject
@@ -357,9 +357,9 @@ class MassMailer(object):
self.headers[name] = value self.headers[name] = value
def send(self): def send(self):
''' """
Process the E-Mails and send them Process the E-Mails and send them
''' """
self.process_mails() self.process_mails()
if len(self.mail_queue) == 0: if len(self.mail_queue) == 0:
self.log.info('No recipients for eMail "%s", bye!', self.subject) self.log.info('No recipients for eMail "%s", bye!', self.subject)

View File

@@ -47,7 +47,7 @@ def set_dirty(event=None, season=None, user=None):
elif user: elif user:
key_to_add = user key_to_add = user
queue_name = 'kyu_dan_ranking_queue' queue_name = 'kyu_dan_ranking_queue'
if key_to_add and queue_name:
recalculation_queue = cache.get(queue_name, set()) recalculation_queue = cache.get(queue_name, set())
recalculation_queue.add(key_to_add) recalculation_queue.add(key_to_add)
cache.set(queue_name, recalculation_queue, 360) cache.set(queue_name, recalculation_queue, 360)

View File

@@ -1,10 +1,10 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
''' """
Created on 19.09.2011 Created on 19.09.2011
@author: christian @author: christian
''' """
# import stuff we need from django # import stuff we need from django
from django.contrib import admin from django.contrib import admin
from . import models, set_dirty from . import models, set_dirty
@@ -45,7 +45,6 @@ class EventRankingAdmin(admin.ModelAdmin):
list_display = ('placement', 'user', 'event', 'avg_placement', 'avg_score', list_display = ('placement', 'user', 'event', 'avg_placement', 'avg_score',
'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty') 'hanchan_count', 'good_hanchans', 'won_hanchans', 'dirty')
list_display_links = ('user',) list_display_links = ('user',)
list_filter = ('event',)
actions = [recalculate] actions = [recalculate]

View File

@@ -1,11 +1,11 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
''' """
Created on 04.10.2011 Created on 04.10.2011
@author: christian @author: christian
''' """
from django.contrib.auth.models import User from django.contrib.auth import get_user_model
import django.forms import django.forms
from django.forms.models import BaseInlineFormSet, inlineformset_factory from django.forms.models import BaseInlineFormSet, inlineformset_factory
from django.utils import timezone from django.utils import timezone
@@ -30,10 +30,10 @@ class HanchanForm(forms.ModelForm):
} }
def clean_start(self): def clean_start(self):
u''' u"""
Das Datum darf nicht in der Zukunft liegen und es muss innerhalb der Das Datum darf nicht in der Zukunft liegen und es muss innerhalb der
Dauer des Events liegen. Dauer des Events liegen.
''' """
start = self.cleaned_data['start'] start = self.cleaned_data['start']
event = self.cleaned_data['event'] event = self.cleaned_data['event']
if start > timezone.now(): if start > timezone.now():
@@ -58,8 +58,8 @@ class HanchanAdminForm(HanchanForm):
class PlayerForm(forms.ModelForm): class PlayerForm(forms.ModelForm):
error_css_class = 'error' error_css_class = 'error'
required_css_class = 'required' required_css_class = 'required'
player_choices = User.objects.filter(groups__in=(1, 2)).distinct() player_choices = get_user_model().objects.filter(groups__in=(1, 2))
player_choices = player_choices.order_by('username') player_choices = player_choices.order_by('username').distinct()
user = forms.ModelChoiceField(player_choices, required=True) user = forms.ModelChoiceField(player_choices, required=True)
comment = forms.CharField( comment = forms.CharField(
widget=forms.widgets.TextInput(attrs={'maxlength': 255}), widget=forms.widgets.TextInput(attrs={'maxlength': 255}),

View File

@@ -4,9 +4,8 @@
Generate Randum Mahjong Hanchans to the the Raning System 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.core.management.base import BaseCommand
from django.utils.translation import ugettext_lazy as _
from events.models import Event from events.models import Event
from mahjong_ranking import models from mahjong_ranking import models
import random import random
@@ -85,7 +84,7 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
num_hanchans = int(options.get('hanchans', 4)) 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 event in Event.objects.all():
for i in range(random.randrange(2,8)): for i in range(random.randrange(2,8)):

View File

@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
Created on 23.05.2011 Created on 23.05.2011
@author: christian @author: christian
''' """
from django.core.cache import cache from django.core.cache import cache
from django.db import transaction from django.db import transaction
from mahjong_ranking import models from mahjong_ranking import models
@@ -11,10 +11,10 @@ from . import logger
class DenormalizationUpdateMiddleware(object): class DenormalizationUpdateMiddleware(object):
''' """
This Class deferres the recalculation for the Otaku XP at the end of a This Class deferres the recalculation for the Otaku XP at the end of a
response. response.
''' """
def process_response(self, request, response): def process_response(self, request, response):
if request.method != 'POST': if request.method != 'POST':
@@ -57,7 +57,7 @@ class DenormalizationUpdateMiddleware(object):
user_id=user_id, season_id=season_id)[0] user_id=user_id, season_id=season_id)[0]
ranking.recalculate() ranking.recalculate()
else: 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) cache.set('ladder_ranking_queue', ladder_ranking_queue, 360)
transaction.commit() transaction.commit()

View File

@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from datetime import date, timedelta 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.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@@ -20,12 +20,12 @@ ladder_seasons = set()
class EventRanking(models.Model): class EventRanking(models.Model):
''' """
Event Rankings funktionieren genauso wie Season Rankings. Event Rankings funktionieren genauso wie Season Rankings.
Sie beschränken sich aber auf einen Event und werden nur dann angestossen, Sie beschränken sich aber auf einen Event und werden nur dann angestossen,
wenn der Event als Turnier markiert wurde. wenn der Event als Turnier markiert wurde.
''' """
user = models.ForeignKey(User) user = models.ForeignKey(settings.AUTH_USER_MODEL)
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
placement = models.PositiveIntegerField(blank=True, null=True) placement = models.PositiveIntegerField(blank=True, null=True)
avg_placement = models.FloatField(default=4) avg_placement = models.FloatField(default=4)
@@ -42,7 +42,7 @@ class EventRanking(models.Model):
return reverse('event-ranking', args=[self.tourney_id]) return reverse('event-ranking', args=[self.tourney_id])
def recalculate(self): def recalculate(self):
''' """
Berechnet die durschnittliche Platzierung und Punkte, u.v.m. neu. Berechnet die durschnittliche Platzierung und Punkte, u.v.m. neu.
Diese Daten werden benötigt um die Platzierung zu erstellen. Sie 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 Das Eigenschaft dirty ist ein altes Überbleibsel, um das Objekt
zur neuberrechnung zu markieren. Mittlerweile wird ein lokaler zur neuberrechnung zu markieren. Mittlerweile wird ein lokaler
Cache dafür verwendet, das ist schneller. Cache dafür verwendet, das ist schneller.
''' """
logger.info(u'Recalculate EventRanking for Player %s in %s', self.user, self.event.name) # @IgnorePep8 logger.info(u'Recalculate EventRanking for Player %s in %s', self.user, self.event.name) # @IgnorePep8
event_hanchans = Player.objects.valid_hanchans(user=self.user_id, event=self.event_id) # @IgnorePep8 event_hanchans = Player.objects.valid_hanchans(user=self.user_id, event=self.event_id) # @IgnorePep8
aggregator = event_hanchans.aggregate( aggregator = event_hanchans.aggregate(
@@ -72,16 +72,20 @@ class EventRanking(models.Model):
class Hanchan(models.Model): class Hanchan(models.Model):
''' """
Ein komplette Runde Mahjong, die aus genau 4 Spielern bestehen muss. Ein komplette Runde Mahjong, die aus genau 4 Spielern bestehen muss.
Es werden aber noch andere Tests durchgeführt, ob sie gültig ist. Es werden aber noch andere Tests durchgeführt, ob sie gültig ist.
Außerdem gehört jede Hanchan zu einer Veranstaltung. Außerdem gehört jede Hanchan zu einer Veranstaltung.
''' """
comment = models.TextField(_('Comment'), blank=True) comment = models.TextField(_('Comment'), blank=True)
confirmed = models.BooleanField(_('Has been Confirmed'), default=True, help_text=_('Only valid and confirmed Hanchans will be counted in the rating.')) # @IgnorePep8 confirmed = models.BooleanField(_('Has been Confirmed'), default=True, help_text=_('Only valid and confirmed Hanchans will be counted in the rating.')) # @IgnorePep8
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
player_names = models.CharField(max_length=127, editable=False) 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 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 start = models.DateTimeField(_('Start'), help_text=_('This is crucial to get the right Hanchans that scores')) # @IgnorePep8
valid = models.BooleanField(_('Is Valid'), default=False) 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) return "Hanchan am {0:%d.%m.%Y} um {0:%H:%M} ({1})".format(self.start, self.player_names)
def check_validity(self): def check_validity(self):
''' """
Prüft ob die Hanchan gültig ist. Prüft ob die Hanchan gültig ist.
4 Spieler müssen genau 100.000 Punkte erreichen, mehr sind nur erlaubt 4 Spieler müssen genau 100.000 Punkte erreichen, mehr sind nur erlaubt
wenn midestens ein Spieler ins Minus (auf 0) geraten ist. Ansonsten wenn midestens ein Spieler ins Minus (auf 0) geraten ist. Ansonsten
wird die Hanchan als ungültig markiert aber trotzdem abgespeichert, wird die Hanchan als ungültig markiert aber trotzdem abgespeichert,
außerdem wird die Begründung zurück gegeben, was nicht gestimmt hat. außerdem wird die Begründung zurück gegeben, was nicht gestimmt hat.
''' """
logger.debug("Hanchan wird geprüft ob er valide ist...") logger.debug("Hanchan wird geprüft ob er valide ist...")
if not self.pk: if not self.pk:
self.valid = False self.valid = False
@@ -132,7 +136,7 @@ class Hanchan(models.Model):
return 'Wir wissen nicht warum, aber das kann nicht passen...' return 'Wir wissen nicht warum, aber das kann nicht passen...'
def clean(self): def clean(self):
''' """
Prüft ob wichtige Vorrausetzungen gegeben sind und aktualisiert ein Prüft ob wichtige Vorrausetzungen gegeben sind und aktualisiert ein
paar Zwischenspeicher, bevor gespeichert wird. 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 Die Gültigkeit wird geprüft und die Sasion in der die Hanchan liegt
wird aktualisert. wird aktualisert.
''' """
logger.debug("Hanchan clean() wurde getriggert!") logger.debug("Hanchan clean() wurde getriggert!")
# if self.pk and self.player_set.distinct().count() != 4: # if self.pk and self.player_set.distinct().count() != 4:
@@ -156,10 +160,10 @@ class Hanchan(models.Model):
return self return self
def compute_player_placements(self): def compute_player_placements(self):
u''' u"""
Bestimmt die Platzierung eines der Spieler einer Hanchan und speichert Bestimmt die Platzierung eines der Spieler einer Hanchan und speichert
diese beim jeweiligen Spieler ab. diese beim jeweiligen Spieler ab.
''' """
logger.debug("Berechne die Platzierungen neu...") logger.debug("Berechne die Platzierungen neu...")
attending_players = self.player_set.select_related('hanchan', 'user') attending_players = self.player_set.select_related('hanchan', 'user')
attending_players = attending_players.order_by('-score') 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) player.save(season_id=self.season_id, mark_dirty=True)
def get_absolute_url(self): def get_absolute_url(self):
''' """
URL zur Hanchanliste des Events wo diese Hanchan gelistet wurde. URL zur Hanchanliste des Events wo diese Hanchan gelistet wurde.
''' """
url = reverse('event-hanchan-list', kwargs={'event': self.event.pk}) url = reverse('event-hanchan-list', kwargs={'event': self.event.pk})
return u'%(url)s#%(pk)d' % {'url': url, 'pk': self.pk} return u'%(url)s#%(pk)d' % {'url': url, 'pk': self.pk}
@@ -201,12 +205,12 @@ class Hanchan(models.Model):
class KyuDanRanking(models.Model): class KyuDanRanking(models.Model):
u''' u"""
Die Einstufung des Spieles im Kyu bzw. Dan System. Die Einstufung des Spieles im Kyu bzw. Dan System.
Im Gegensatz zum Ladder Ranking ist das nicht Saison gebunden. Im Gegensatz zum Ladder Ranking ist das nicht Saison gebunden.
daher läuft es getrennt. daher läuft es getrennt.
''' """
user = models.OneToOneField(User) user = models.OneToOneField(settings.AUTH_USER_MODEL)
dan = models.PositiveSmallIntegerField(blank=True, null=True) dan = models.PositiveSmallIntegerField(blank=True, null=True)
dan_points = models.PositiveIntegerField(default=0) dan_points = models.PositiveIntegerField(default=0)
kyu = models.PositiveSmallIntegerField(default=10, blank=True, null=True) 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) return u"%s - %d. Kyu" % (self.user.username, self.kyu)
def append_3_in_a_row_bonuspoints(self, hanchan): def append_3_in_a_row_bonuspoints(self, hanchan):
u''' u"""
Wenn der Spieler 3 Siege in folge hatte, bekommt er so viele Punkte Wenn der Spieler 3 Siege in folge hatte, bekommt er so viele Punkte
das er einen Dan Rang aufsteigt. Dies wird als Kommentar abgespeichert, das er einen Dan Rang aufsteigt. Dies wird als Kommentar abgespeichert,
um es besser nachvollziehen zu können. um es besser nachvollziehen zu können.
''' """
if self.dan and hanchan.placement == 1: if self.dan and hanchan.placement == 1:
self.wins_in_a_row += 1 self.wins_in_a_row += 1
@@ -259,12 +263,12 @@ class KyuDanRanking(models.Model):
self.dan_points += bonus_points self.dan_points += bonus_points
def append_tournament_bonuspoints(self, player): def append_tournament_bonuspoints(self, player):
''' """
Prüft ob es die letzte Hanchan in einem Turnier war. Wenn ja werden Prüft ob es die letzte Hanchan in einem Turnier war. Wenn ja werden
bei Bedarf Bonuspunkte vergeben, falls der Spieler das Turnier gewonnen bei Bedarf Bonuspunkte vergeben, falls der Spieler das Turnier gewonnen
hat. hat.
:param player: Ein Player Objekt :param player: Ein Player Objekt
''' """
bonus_points = 0 bonus_points = 0
current_event = player.hanchan.event current_event = player.hanchan.event
if not current_event.is_tournament: if not current_event.is_tournament:
@@ -300,10 +304,10 @@ class KyuDanRanking(models.Model):
return reverse('player-kyu-score', args=[self.user.username]) return reverse('player-kyu-score', args=[self.user.username])
def recalculate(self): def recalculate(self):
''' """
Fetches all valid Hanchans from this Player and recalculates his Fetches all valid Hanchans from this Player and recalculates his
Kyu/Dan Ranking. Kyu/Dan Ranking.
''' """
logger.debug("recalculating Kyu/Dan punkte for %s...", self.user) logger.debug("recalculating Kyu/Dan punkte for %s...", self.user)
valid_hanchans = Player.objects.valid_hanchans(user=self.user_id) valid_hanchans = Player.objects.valid_hanchans(user=self.user_id)
valid_hanchans = valid_hanchans.order_by('hanchan__start') valid_hanchans = valid_hanchans.order_by('hanchan__start')
@@ -326,10 +330,10 @@ class KyuDanRanking(models.Model):
self.save(force_update=True) self.save(force_update=True)
def update_points(self, player): def update_points(self, player):
''' """
Berechne die Kyu bzw. Dan Punkte für ein Spiel neu. Berechne die Kyu bzw. Dan Punkte für ein Spiel neu.
:param player: Das Player Objekt das neuberechnet werden soll. :param player: Das Player Objekt das neuberechnet werden soll.
''' """
player.bonus_points = 0 player.bonus_points = 0
player.comment = "" player.comment = ""
player.dan_points = None player.dan_points = None
@@ -403,7 +407,7 @@ class KyuDanRanking(models.Model):
class LadderRanking(models.Model): class LadderRanking(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(settings.AUTH_USER_MODEL)
season = models.ForeignKey('LadderSeason') season = models.ForeignKey('LadderSeason')
placement = models.PositiveIntegerField(blank=True, null=True) placement = models.PositiveIntegerField(blank=True, null=True)
avg_placement = models.FloatField(blank=True, null=True) avg_placement = models.FloatField(blank=True, null=True)
@@ -441,9 +445,9 @@ class LadderRanking(models.Model):
class LadderSeasonManager(models.Manager): class LadderSeasonManager(models.Manager):
def current(self): def current(self):
''' """
Returns the current season and caches the result for 12 hours Returns the current season and caches the result for 12 hours
''' """
current_season = cache.get('current_mahjong_season') current_season = cache.get('current_mahjong_season')
if not current_season: if not current_season:
try: try:
@@ -456,10 +460,10 @@ class LadderSeasonManager(models.Manager):
return current_season return current_season
def get_by_date(self, deadline): def get_by_date(self, deadline):
''' """
returns the season that where running on the given date. returns the season that where running on the given date.
:param deadline: the date you're intrested in :param deadline: the date you're intrested in
''' """
try: try:
season = self.filter(start__lte=deadline, end__gte=deadline) season = self.filter(start__lte=deadline, end__gte=deadline)
return season[0] return season[0]
@@ -468,9 +472,9 @@ class LadderSeasonManager(models.Manager):
class LadderSeason(models.Model): class LadderSeason(models.Model):
u''' u"""
Eine Saison für das Kasu interne Ladder-Ranking. Eine Saison für das Kasu interne Ladder-Ranking.
''' """
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
start = models.DateField() start = models.DateField()
end = models.DateField() end = models.DateField()
@@ -488,10 +492,13 @@ class LadderSeason(models.Model):
def recalculate(self): def recalculate(self):
logger.info(u'Recalculate LadderSeason %s', self.name) logger.info(u'Recalculate LadderSeason %s', self.name)
self.ladderranking_set.update(placement=None) 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 placement = 1
ladder_rankings = self.ladderranking_set.filter(hanchan_count__gt=MIN_HANCHANS_FOR_LADDER) # @IgnorePep8 for ranking in ladderrankings_for_placement:
ladder_rankings = ladder_rankings.order_by('avg_placement', '-avg_score') # @IgnorePep8
for ranking in ladder_rankings:
ranking.placement = placement ranking.placement = placement
ranking.save(force_update=True) ranking.save(force_update=True)
placement += 1 placement += 1
@@ -556,12 +563,28 @@ class PlayerManager(models.Manager):
class Player(models.Model): class Player(models.Model):
hanchan = models.ForeignKey(Hanchan) hanchan = models.ForeignKey(Hanchan)
user = models.ForeignKey(User) user = models.ForeignKey(settings.AUTH_USER_MODEL)
score = models.PositiveIntegerField(default=0) score = models.PositiveIntegerField(default=0)
placement = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 placement = models.PositiveSmallIntegerField(
kyu_points = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 blank=True,
dan_points = models.PositiveSmallIntegerField(blank=True, null=True, default=None) # @IgnorePep8 null=True,
bonus_points = models.PositiveSmallIntegerField(blank=True, null=True, default=0) # @IgnorePep8 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) comment = models.TextField(_('Comment'), blank=True)
objects = PlayerManager() objects = PlayerManager()

View File

@@ -18,7 +18,7 @@
{% for player in hanchan.player_set.all %} {% for player in hanchan.player_set.all %}
<div class="player" > <div class="player" >
<a href="{% url 'player-ladder-score' player.user %}"><img <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="" class="avatar" alt=""
title="{% if player.dan_points != None %}Dan P.: {{player.dan_points}}{% else %}Kyu P.: {{player.kyu_points}}{% endif %} - {{player.comment}}"/></a> 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> <h4>{{player.placement}}. - <a href="{% url 'player-ladder-score' player.user %}">{{ player.user }}</a></h4>

View File

@@ -2,9 +2,8 @@
{% load i18n %} {% load i18n %}
{% block additional_nav_elements %} {% 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 %} {% 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 %} {% endif %}
</ul>
{% endblock %} {% endblock %}

View File

@@ -18,7 +18,7 @@
<tr> <tr>
<th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Date' %}</th>
<th rowspan="2">{% trans 'Event' %}</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 rowspan="2">{% trans 'Placement' %}</th>
<th colspan="4">{% trans 'Players' %}</th> <th colspan="4">{% trans 'Players' %}</th>
<th rowspan="2">{% trans 'Dan Points' %}</th> <th rowspan="2">{% trans 'Dan Points' %}</th>
@@ -28,7 +28,7 @@
<tr> <tr>
<th>1.</th> <th>1.</th>
<th>2.</th> <th>2.</th>
<th>3.<//th> <th>3.</th>
<th>4.</th> <th>4.</th>
</tr> </tr>
</thead> </thead>
@@ -46,10 +46,10 @@
<td>{{ result.comment }}</td> <td>{{ result.comment }}</td>
<td> <td>
{% if perms.mahjong_ranking.delete_hanchan %} {% 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 %} {% endif %}
{% if perms.mahjong_ranking.change_hanchan %} {% 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 %} {% endif %}
</td> </td>
</tr> </tr>

View File

@@ -16,7 +16,7 @@
<table> <table>
<thead><tr> <thead><tr>
<th>{% trans 'Event' %}</th> <th>{% trans 'Event' %}</th>
<th>{% trans 'Start' %}<//th> <th>{% trans 'Start' %}</th>
<th colspan="4">{% trans 'Players' %}</th> <th colspan="4">{% trans 'Players' %}</th>
<th>{% trans 'Placement' %}</th> <th>{% trans 'Placement' %}</th>
<th>{% trans 'Kyu Points' %}</th> <th>{% trans 'Kyu Points' %}</th>
@@ -36,10 +36,10 @@
<td>{{ result.comment }}</td> <td>{{ result.comment }}</td>
<td> <td>
{% if perms.mahjong_ranking.delete_hanchan %} {% 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 %} {% endif %}
{% if perms.mahjong_ranking.change_hanchan %} {% 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 %} {% endif %}
</td> </td>
</tr> </tr>

View File

@@ -17,7 +17,7 @@
<tr> <tr>
<th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Date' %}</th>
<th rowspan="2">{% trans 'Event' %}</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 rowspan="2">{% trans 'Placement' %}</th>
<th colspan="4">{% trans 'Players' %}</th> <th colspan="4">{% trans 'Players' %}</th>
<th rowspan="2">{% trans 'Kyu Points' %}</th> <th rowspan="2">{% trans 'Kyu Points' %}</th>
@@ -26,7 +26,7 @@
<tr> <tr>
<th>1.</th> <th>1.</th>
<th>2.</th> <th>2.</th>
<th>3.<//th> <th>3.</th>
<th>4.</th> <th>4.</th>
</tr> </tr>
</thead> </thead>
@@ -43,10 +43,10 @@
<td class="center">{{result.kyu_points}}</td> <td class="center">{{result.kyu_points}}</td>
<td> <td>
{% if perms.mahjong_ranking.delete_hanchan %} {% 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 %} {% endif %}
{% if perms.mahjong_ranking.change_hanchan %} {% 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 %} {% endif %}
</td> </td>
</tr> </tr>

View File

@@ -18,7 +18,7 @@
<tr> <tr>
<th rowspan="2">{% trans 'Date' %}</th> <th rowspan="2">{% trans 'Date' %}</th>
<th rowspan="2">{% trans 'Event' %}</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 rowspan="2">{% trans 'Placement' %}</th>
<th colspan="4">{% trans 'Players' %}</th> <th colspan="4">{% trans 'Players' %}</th>
<th rowspan="2"></th> <th rowspan="2"></th>
@@ -26,7 +26,7 @@
<tr> <tr>
<th>1.</th> <th>1.</th>
<th>2.</th> <th>2.</th>
<th>3.<//th> <th>3.</th>
<th>4.</th> <th>4.</th>
</tr> </tr>
</thead> </thead>
@@ -42,10 +42,10 @@
{% endfor %} {% endfor %}
<td> <td>
{% if perms.mahjong_ranking.delete_hanchan %} {% 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 %} {% endif %}
{% if perms.mahjong_ranking.change_hanchan %} {% 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 %} {% endif %}
</td> </td>
</tr> </tr>

View File

@@ -1,17 +1,16 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
''' """
Created on 03.10.2011 Created on 03.10.2011
@author: christian @author: christian
''' """
from django.conf.urls import * # @UnusedWildImport from django.conf.urls import * # @UnusedWildImport
import views import views
urlpatterns = patterns('', urlpatterns = patterns(
url(r'^$', '',
views.LadderRankingList.as_view(), url(r'^$', views.LadderRankingList.as_view(), name="mahjong-ladder"),
name="mahjong-ladder"),
url(r'archive/$', url(r'archive/$',
views.LadderRankingList.as_view(), views.LadderRankingList.as_view(),
kwargs={'is_archive': True}, kwargs={'is_archive': True},

View File

@@ -1,18 +1,20 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
import urllib
from django.contrib import auth, messages from django.contrib import auth, messages
from django.core.urlresolvers import reverse 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.utils.translation import gettext as _
from django.views import generic 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 import xlwt
from django import http
import urllib from events.models import Event
from . import forms, models
from membership.models import Membership from membership.models import Membership
from utils.mixins import LoginRequiredMixin, PermissionRequiredMixin
kyu_dan_order = { kyu_dan_order = {
'+full_name': ('user__last_name', 'user__first_name'), '+full_name': ('user__last_name', 'user__first_name'),
@@ -29,10 +31,10 @@ kyu_dan_order = {
class DeleteHanchan(PermissionRequiredMixin, generic.DeleteView): class DeleteHanchan(PermissionRequiredMixin, generic.DeleteView):
''' """
Fragt zuerst nach, ob die Hanchan wirklich gelöscht werden soll. Fragt zuerst nach, ob die Hanchan wirklich gelöscht werden soll.
Wir die Frage mit "Ja" beantwortet, wird die die Hanchan gelöscht. Wir die Frage mit "Ja" beantwortet, wird die die Hanchan gelöscht.
''' """
form_class = forms.HanchanForm form_class = forms.HanchanForm
model = models.Hanchan model = models.Hanchan
permission_required = 'mahjong_ranking.delete_hanchan' permission_required = 'mahjong_ranking.delete_hanchan'
@@ -44,10 +46,10 @@ class DeleteHanchan(PermissionRequiredMixin, generic.DeleteView):
class HanchanForm(PermissionRequiredMixin, generic.UpdateView): class HanchanForm(PermissionRequiredMixin, generic.UpdateView):
''' """
Ein Formular um eine neue Hanchan anzulegen, bzw. eine bestehende zu Ein Formular um eine neue Hanchan anzulegen, bzw. eine bestehende zu
bearbeitsen bearbeitsen
''' """
form_class = forms.HanchanForm form_class = forms.HanchanForm
model = models.Hanchan model = models.Hanchan
permission_required = 'mahjong_ranking.add_hanchan' permission_required = 'mahjong_ranking.add_hanchan'
@@ -60,7 +62,7 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView):
else: else:
formset.save() formset.save()
self.object = form.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): def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data( return self.render_to_response(self.get_context_data(
@@ -106,10 +108,10 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView):
return context return context
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
''' """
:param request: :param request:
''' """
self.object = self.get_object() self.object = self.get_object()
form = self.get_form(self.get_form_class()) form = self.get_form(self.get_form_class())
formset = self.get_formset() formset = self.get_formset()
@@ -131,9 +133,9 @@ class HanchanForm(PermissionRequiredMixin, generic.UpdateView):
class EventHanchanList(generic.ListView): class EventHanchanList(generic.ListView):
''' """
Auflistung aller Hanchan die während der Veranstaltung gespielt wurden. Auflistung aller Hanchan die während der Veranstaltung gespielt wurden.
''' """
model = models.Hanchan model = models.Hanchan
def get_queryset(self): def get_queryset(self):
@@ -144,7 +146,7 @@ class EventHanchanList(generic.ListView):
queryset = queryset.order_by('start') queryset = queryset.order_by('start')
return queryset return queryset
except models.Event.DoesNotExist: except models.Event.DoesNotExist:
raise Http404(_('Event does not exist')) raise django.http.Http404(_('Event does not exist'))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = generic.ListView.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): class EventRankingList(generic.ListView):
''' """
Anzeige des Eventrankings, daß erstellt wurde falls der Termin als internes Anzeige des Eventrankings, daß erstellt wurde falls der Termin als internes
Turnier markiert wurde. Turnier markiert wurde.
''' """
model = models.EventRanking model = models.EventRanking
def get_queryset(self): def get_queryset(self):
@@ -166,7 +168,7 @@ class EventRankingList(generic.ListView):
queryset = queryset.prefetch_related() queryset = queryset.prefetch_related()
return queryset return queryset
except models.Event.DoesNotExist: except models.Event.DoesNotExist:
raise Http404(_('Event does not exist')) raise django.http.Http404(_('Event does not exist'))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = generic.ListView.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): class KyuDanRankingList(generic.ListView):
''' """
Anzeige aller Spiele mit ihrem Kyu bzw Dan Grad. Anzeige aller Spiele mit ihrem Kyu bzw Dan Grad.
''' """
models.KyuDanRanking
default_order = '-score' default_order = '-score'
order_by = '' order_by = ''
paginate_by = 25 paginate_by = 25
@@ -213,7 +214,7 @@ class LadderRankingList(generic.ListView):
else: else:
self.season = models.LadderSeason.objects.current() self.season = models.LadderSeason.objects.current()
except models.LadderSeason.DoesNotExist: 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() queryset = models.LadderRanking.objects.filter(season=self.season, placement__isnull=False).select_related()
return queryset return queryset
@@ -238,7 +239,7 @@ class LadderRankingExcel(generic.View):
def get(self, request, **kwargs): def get(self, request, **kwargs):
self.queryset = self.team.members.all() 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')) filename = urllib.quote(self.filename.encode('utf-8'))
response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % filename 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, 9, profile.weight or None)
self.set_col(sheet, current_row, 10, profile.emergency_contact 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) self.set_col(sheet, current_row, 11, profile.emergency_phone or None)
except models.MemberProfile.DoesNotExist: except Membership.DoesNotExist:
pass pass
current_row += 1 current_row += 1
for column in range(0, 13): for column in range(0, 13):
print column, self.max_colwidth[column]
sheet.col(column).width = (self.max_colwidth[column] + 1) * 256 sheet.col(column).width = (self.max_colwidth[column] + 1) * 256
workbook.save(response) workbook.save(response)
@@ -294,10 +294,10 @@ class PlayerScore(LoginRequiredMixin, generic.ListView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
try: 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] self.membership = Membership.objects.get_or_create(user=self.user)[0]
except auth.models.User.DoesNotExist: except auth.get_user_model().DoesNotExist:
raise Http404(_("No user found matching the name %s") % self.kwargs.get('username')) raise django.http.Http404(_("No user found matching the name %s") % self.kwargs.get('username'))
return generic.ListView.get(self, request, *args, **kwargs) return generic.ListView.get(self, request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@@ -305,13 +305,13 @@ class PlayerScore(LoginRequiredMixin, generic.ListView):
context['membership'] = self.membership context['membership'] = self.membership
try: try:
context['kyu_dan_ranking'] = models.KyuDanRanking.objects.get(user=self.user) context['kyu_dan_ranking'] = models.KyuDanRanking.objects.get(user=self.user)
except: except models.KyuDanRanking.DoesNotExist:
context['ranking'] = None context['ranking'] = None
try: try:
context['ladder_ranking'] = models.LadderRanking.objects.get( context['ladder_ranking'] = models.LadderRanking.objects.get(
user=self.user, user=self.user,
season=models.LadderSeason.objects.current()) season=models.LadderSeason.objects.current())
except: except models.LadderRanking.DoesNotExist:
context['ladder_ranking'] = models.LadderRanking(user=self.user) context['ladder_ranking'] = models.LadderRanking(user=self.user)
return context return context
@@ -343,10 +343,8 @@ class PlayerLadderScore(PlayerScore):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = PlayerScore.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 = models.LadderRanking.objects.filter(user=self.user).select_related('user')
season_list = season_list.values_list('id', 'season__name') season_list = season_list.values_list('id', 'season__name')
context['season'] = self.season context['season'] = self.season
context['seasons_select_form'] = forms.SeasonSelectForm(user=self.user) context['seasons_select_form'] = forms.SeasonSelectForm(user=self.user)
context['seasons_select_field'] = django.forms.ChoiceField(choices=season_list) context['seasons_select_field'] = django.forms.ChoiceField(choices=season_list)

View File

@@ -1,8 +1,8 @@
''' """
Created on 19.09.2011 Created on 19.09.2011
@author: christian @author: christian
''' """
# import stuff we need from django # import stuff we need from django
from django.contrib import admin from django.contrib import admin
from membership.models import Membership, ActivationRequest 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 = Membership.objects.get(username=activation.user.username)
membership.save() membership.save()
activation.activate() activation.activate()
activate_user.short_description = _('Activate selected User') activate_user.short_description = _('Activate selected User')
@@ -22,6 +24,8 @@ def cleanup_activation(modeladmin, request, queryset):
for activation in queryset: for activation in queryset:
if activation.expired: if activation.expired:
activation.user.delete() activation.user.delete()
cleanup_activation.short_description = _("Cleanup selected Activation Requests") cleanup_activation.short_description = _("Cleanup selected Activation Requests")
@@ -39,7 +43,8 @@ class MembershipAdmin(admin.ModelAdmin):
) )
list_editable = ('confirmed', 'paid_until',) list_editable = ('confirmed', 'paid_until',)
list_display_links = ('nickname',) list_display_links = ('nickname',)
fieldsets = ((None, { fieldsets = (
(None, {
'fields': ('gender', ('first_name', 'last_name'), ('email', 'website')) 'fields': ('gender', ('first_name', 'last_name'), ('email', 'website'))
}), }),
(_('Membership'), { (_('Membership'), {
@@ -50,6 +55,8 @@ class MembershipAdmin(admin.ModelAdmin):
) )
ordering = ('nickname',) ordering = ('nickname',)
search_fields = ('nickname', 'first_name', 'last_name',) search_fields = ('nickname', 'first_name', 'last_name',)
admin.site.register(Membership, MembershipAdmin) admin.site.register(Membership, MembershipAdmin)
@@ -59,4 +66,5 @@ class RegistrationAdmin(admin.ModelAdmin):
search_fields = ('user__username', 'user__first_name') search_fields = ('user__username', 'user__first_name')
actions = [cleanup_activation, activate_user] actions = [cleanup_activation, activate_user]
admin.site.register(ActivationRequest, RegistrationAdmin) admin.site.register(ActivationRequest, RegistrationAdmin)

View File

@@ -1,11 +1,11 @@
''' """
Created on 03.10.2011 Created on 03.10.2011
@author: Christian @author: Christian
''' """
from . import models from . import models
from django.conf import settings 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.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from utils.html5 import forms from utils.html5 import forms
@@ -26,29 +26,25 @@ class MembershipForm(forms.ModelForm):
) )
def clean_birthday(self): def clean_birthday(self):
if self.cleaned_data['membership'] \ if self.cleaned_data['membership'] and not self.cleaned_data['birthday']:
and not self.cleaned_data['birthday']:
raise forms.ValidationError(_('For your membership, we need this. \ raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.')) Please fill out this field yet.'))
return self.cleaned_data['birthday'] return self.cleaned_data['birthday']
def clean_telephone(self): def clean_telephone(self):
if self.cleaned_data['membership'] \ if self.cleaned_data['membership'] and not self.cleaned_data['telephone']:
and not self.cleaned_data['telephone']:
raise forms.ValidationError(_('For your membership, we need this. \ raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.')) Please fill out this field yet.'))
return self.cleaned_data['telephone'] return self.cleaned_data['telephone']
def clean_street_name(self): def clean_street_name(self):
if self.cleaned_data['membership'] \ if self.cleaned_data['membership'] and not self.cleaned_data['street_name']:
and not self.cleaned_data['street_name']:
raise forms.ValidationError(_('For your membership, we need this. \ raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.')) Please fill out this field yet.'))
return self.cleaned_data['street_name'] return self.cleaned_data['street_name']
def clean_post_code(self): def clean_post_code(self):
if self.cleaned_data['membership'] \ if self.cleaned_data['membership'] and not self.cleaned_data['post_code']:
and not self.cleaned_data['post_code']:
raise forms.ValidationError(_('For your membership, we need this. \ raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.')) Please fill out this field yet.'))
return self.cleaned_data['post_code'] return self.cleaned_data['post_code']
@@ -87,25 +83,27 @@ class RegistrationForm(forms.ModelForm):
recaptcha = forms.ReCaptchaField() recaptcha = forms.ReCaptchaField()
class Meta: class Meta:
model = User model = auth.get_user_model()
fields = ('first_name', 'last_name', 'username', 'email',) fields = ('first_name', 'last_name', 'username', 'email',)
def clean_username(self): def clean_username(self):
''' """
Validate that the username is not already in use. Validate that the username is not already in use.
''' """
try: try:
User.objects.get(username__iexact=self.cleaned_data['username']) auth.get_user_model().objects.get(
except User.DoesNotExist: username__iexact=self.cleaned_data['username']
)
except auth.get_user_model().DoesNotExist:
return self.cleaned_data['username'] return self.cleaned_data['username']
raise forms.ValidationError(_(u'This username is already taken. \ raise forms.ValidationError(_(u'This username is already taken. \
Please choose another.')) Please choose another.'))
def clean_email(self): def clean_email(self):
''' """
Validate that the supplied email address is unique for the site. 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 \ raise forms.ValidationError(_(u'This email address is already in \
use. Please supply a different email address.')) use. Please supply a different email address.'))
return self.cleaned_data['email'] return self.cleaned_data['email']

View File

@@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.utils.translation import ugettext_lazy as _
from membership.models import ActivationRequest from membership.models import ActivationRequest
class Command(BaseCommand): class Command(BaseCommand):
help = "Delete all expired user registrations from the database" help = "Delete all expired user registrations from the database"
def handle(self, *args, **options): def handle(self, *args, **options):
for activation in ActivationRequest.objects.expired(): for activation in ActivationRequest.objects.expired():
activation.user.delete() activation.user.delete()

View File

@@ -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. 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.contrib.sessions.models import Session
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand
from django.utils.translation import ugettext_lazy as _
from optparse import make_option from optparse import make_option
@@ -19,29 +19,32 @@ class Command(BaseCommand):
args = '<session_key session_key ...>' args = '<session_key session_key ...>'
help = 'If the session still exists find it and show the related User' help = 'If the session still exists find it and show the related User'
option_list = BaseCommand.option_list + ( option_list = BaseCommand.option_list + (
make_option('--delete', make_option(
'--delete',
action='store_true', action='store_true',
dest='delete', dest='delete',
default=False, default=False,
help='Delete the Useraccount'), help='Delete the Useraccount'
make_option('--ban', ),
make_option(
'--ban',
action='store_true', action='store_true',
dest='ban', dest='ban',
default=False, default=False,
help='Ban the Useraccount'), help='Ban the Useraccount'
),
) )
def handle(self, *args, **options): def handle(self, *args, **options):
for session_key in args: for session_key in args:
try: try:
session = Session.objects.get(session_key=session_key) session = Session.objects.get(session_key=session_key)
uid = session.get_decoded().get('_auth_user_id') 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: except Session.DoesNotExist:
self.stderr.write('Session "%s" does not exist' % session_key) self.stderr.write('Session "%s" does not exist' % session_key)
continue continue
except User.DoesNotExist: except settings.AUTH_USER_MODEL.DoesNotExist:
self.stderr.write('Session "%s" has no registed User' % session_key) self.stderr.write('Session "%s" has no registed User' % session_key)
continue continue
if options['delete']: if options['delete']:

View File

@@ -4,7 +4,6 @@ from . import PAID_MEMBERSHIP_GROUP
from datetime import timedelta from datetime import timedelta
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models
@@ -23,29 +22,29 @@ GENDER_CHOICES = (
def get_upload_path(instance, filename): def get_upload_path(instance, filename):
''' """
Erstellt den Pfad und Dateinamen für den Upload dynmisch. Erstellt den Pfad und Dateinamen für den Upload dynmisch.
@param instance: The Membership Object for the uploaded image @param instance: The Membership Object for the uploaded image
@param filename: the filename of the uploaded image @param filename: the filename of the uploaded image
''' """
extension = path.splitext(filename)[1] extension = path.splitext(filename)[1]
return 'membership/%s%s' % (instance.user.username, extension) return 'membership/%s%s' % (instance.user.username, extension)
class ActivationManager(models.Manager): class ActivationManager(models.Manager):
''' """
Manages pending user registrations Manages pending user registrations
''' """
def activate(self, activation_key): def activate(self, activation_key):
''' """
searches the pending registrations for the given activation key. searches the pending registrations for the given activation key.
Set the corresponding user to active, if the key was found Set the corresponding user to active, if the key was found
and the key has not expired yet.s and the key has not expired yet.s
@param activation_key: the key found in the activation email @param activation_key: the key found in the activation email
''' """
try: try:
activation_request = self.get(activation_key=activation_key) activation_request = self.get(activation_key=activation_key)
if activation_request.expired(): if activation_request.expired():
@@ -61,10 +60,10 @@ class ActivationManager(models.Manager):
return False return False
def create_pending_registration(self, user): def create_pending_registration(self, user):
''' """
creates a PendingActivation instance with an random activation key. creates a PendingActivation instance with an random activation key.
@param user: the user that requests activation. @param user: the user that requests activation.
''' """
salt = str(random.random()) salt = str(random.random())
activation_key = hashlib.sha1(salt + user.username).hexdigest() activation_key = hashlib.sha1(salt + user.username).hexdigest()
@@ -78,12 +77,16 @@ class ActivationManager(models.Manager):
class ActivationRequest(models.Model): class ActivationRequest(models.Model):
''' """
Each ActivationRequest contains an activation key and an user. Each ActivationRequest contains an activation key and an user.
The key will be send by email to the 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. 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) activation_key = models.CharField(_('activation key'), max_length=40)
objects = ActivationManager() objects = ActivationManager()
@@ -115,6 +118,7 @@ class ActivationRequest(models.Model):
return True return True
else: else:
return False return False
expired.boolean = True expired.boolean = True
@property @property
@@ -135,28 +139,26 @@ class ActivationRequest(models.Model):
class MembershipManager(models.Manager): class MembershipManager(models.Manager):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
''' """
First try's to fetch the requested Membership Object from the Database, First try's to fetch the requested Membership Object from the Database,
if the requestetd Membership does not Exists (yet) try to fetch the if the requestetd Membership does not Exists (yet) try to fetch the
corresponding User, and create the Membership with the filled in corresponding User, and create the Membership with the filled in
Userdata. Userdata.
''' """
try: try:
if 'username' in kwargs: if 'username' in kwargs:
return models.Manager.get(self, return models.Manager.get(self,
user__username=kwargs['username'] user__username=kwargs['username'])
)
else: else:
return models.Manager.get(self, *args, **kwargs) return models.Manager.get(self, *args, **kwargs)
except FieldError: except FieldError:
user = User.objects.get(*args, **kwargs) user = settings.AUTH_USER_MODEL.objects.get(*args, **kwargs)
except Membership.DoesNotExist: except Membership.DoesNotExist:
if 'user' in kwargs: if 'user' in kwargs:
user = User.objects.get(pk=kwargs['user'].id) user = settings.AUTH_USER_MODEL.objects.get(pk=kwargs['user'].id)
else: else:
user = User.objects.get(*args, **kwargs) user = settings.AUTH_USER_MODEL.objects.get(*args, **kwargs)
membership = Membership( membership = Membership(
user=user, user=user,
@@ -169,7 +171,10 @@ class MembershipManager(models.Manager):
class Membership(models.Model): class Membership(models.Model):
user = models.OneToOneField(User) user = models.ForeignKey(
settings.AUTH_USER_MODEL,
unique=True
)
nickname = models.SlugField(_('Nickname'), unique=True) nickname = models.SlugField(_('Nickname'), unique=True)
gender = models.CharField( gender = models.CharField(
_("Gender"), _("Gender"),
@@ -186,39 +191,46 @@ class Membership(models.Model):
blank=True, blank=True,
null=True null=True
) )
membership = models.BooleanField(_('Membership'), membership = models.BooleanField(
_('Membership'),
default=False, default=False,
help_text=_('Yes, I confirm that I am in agreement with the statutes \ help_text=_('Yes, I confirm that I am in agreement with the statutes \
and would like to become a member.') and would like to become a member.')
) )
birthday = models.DateField(_("Birthday Date"), blank=True, null=True) birthday = models.DateField(_("Birthday Date"), blank=True, null=True)
telephone = models.CharField(_("Telephone"), telephone = models.CharField(
_("Telephone"),
max_length=30, max_length=30,
blank=True, blank=True,
null=True null=True
) )
street_name = models.CharField(_("Address"), street_name = models.CharField(
_("Address"),
max_length=75, max_length=75,
blank=True, blank=True,
null=True null=True
) )
post_code = models.PositiveSmallIntegerField(_("Postcode"), post_code = models.PositiveSmallIntegerField(
_("Postcode"),
blank=True, blank=True,
null=True null=True
) )
city = models.CharField(_("Town/City"), city = models.CharField(
_("Town/City"),
max_length=75, max_length=75,
blank=True, blank=True,
null=True null=True
) )
deposit = models.PositiveSmallIntegerField(default=0, editable=False) deposit = models.PositiveSmallIntegerField(default=0, editable=False)
registration_date = models.DateField(auto_now_add=True, 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, blank=True,
null=True, null=True,
editable=True editable=True
) )
confirmed = models.BooleanField(_('Confirmed'), confirmed = models.BooleanField(
_('Confirmed'),
default=False, default=False,
help_text=_('This person has paid the membership fee.') help_text=_('This person has paid the membership fee.')
) )
@@ -258,7 +270,8 @@ class Membership(models.Model):
self.email = self.user.email self.email = self.user.email
def get_absolute_url(self): def get_absolute_url(self):
return reverse('membership-details', return reverse(
'membership-details',
kwargs={'username': self.user.username} kwargs={'username': self.user.username}
) )

View File

@@ -7,15 +7,18 @@ class ResizeThumbnail(processors.Resize):
height = 60 height = 60
crop = True crop = True
class ResizeProfile(processors.Resize): class ResizeProfile(processors.Resize):
width = 140 width = 140
height = 140 height = 140
crop = True crop = True
class Thumbnail(ImageSpec): class Thumbnail(ImageSpec):
pre_cache = True pre_cache = True
processors = (ResizeThumbnail,) processors = (ResizeThumbnail,)
class Profile(ImageSpec): class Profile(ImageSpec):
pre_cache = False pre_cache = False
processors = (ResizeProfile,) processors = (ResizeProfile,)

View File

@@ -2,7 +2,7 @@
<table> <table>
<thead><tr> <thead><tr>
<th>{% trans 'Start' %}<//th> <th>{% trans 'Start' %}</th>
<th>{% trans 'Event' %}</th> <th>{% trans 'Event' %}</th>
<th colspan="4">{% trans 'Players' %}</th> <th colspan="4">{% trans 'Players' %}</th>
<th>{% trans 'Kyu Points' %}</th> <th>{% trans 'Kyu Points' %}</th>

View File

@@ -1,14 +1,15 @@
''' """
Created on 03.10.2011 Created on 03.10.2011
@author: christian @author: christian
''' """
from django.conf.urls import * # @UnusedWildImport from django.conf.urls import * # @UnusedWildImport
from . import views from . import views
urlpatterns = patterns('', urlpatterns = patterns(
'',
url('', include('social.apps.django_app.urls', namespace='social')), url('', include('social.apps.django_app.urls', namespace='social')),
url('', include('django.contrib.auth.urls')), url('', include('django.contrib.auth.urls')),
url(r'^register/$', url(r'^register/$',

View File

@@ -4,16 +4,17 @@ from django.contrib import auth, messages
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views import generic from django.views import generic
from mahjong_ranking.models import KyuDanRanking, LadderRanking, LadderSeason from mahjong_ranking.models import KyuDanRanking, LadderRanking, LadderSeason
import forms
import models
from utils import mixins from utils import mixins
from . import forms, models
class ActivateRegistration(generic.DetailView): class ActivateRegistration(generic.DetailView):
''' """
Activates the Registration of an User and logs him in Activates the Registration of an User and logs him in
''' """
template_name = 'membership/activation_error.html' template_name = 'membership/activation_error.html'
def get(self, request, **kwargs): def get(self, request, **kwargs):
@@ -79,7 +80,7 @@ class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
if self.kwargs.get('username'): 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(): elif self.request.user.is_authenticated():
return models.Membership.objects.get(user=self.request.user) return models.Membership.objects.get(user=self.request.user)
@@ -88,13 +89,13 @@ class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView):
try: try:
context['kyu_dan_ranking'] = KyuDanRanking.objects.get( context['kyu_dan_ranking'] = KyuDanRanking.objects.get(
user_id=self.object.user_id) user_id=self.object.user_id)
except: except KyuDanRanking.DoesNotExist:
context['kyu_dan_ranking'] = None context['kyu_dan_ranking'] = None
try: try:
context['ladder_ranking'] = LadderRanking.objects.get( context['ladder_ranking'] = LadderRanking.objects.get(
user_id=self.object.user_id, user_id=self.object.user_id,
season=LadderSeason.objects.current()) season=LadderSeason.objects.current())
except: except LadderRanking.DoesNotExist:
context['ladder_ranking'] = LadderRanking(user=self.object.user) context['ladder_ranking'] = LadderRanking(user=self.object.user)
return context return context

View File

@@ -1,5 +1,14 @@
{% load i18n %} {% load i18n %}
<!DOCTYPE HTML> <!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
</body>
</html>>
<html> <html>
<head> <head>
<title>Kasu - {% block title %}{{ current_top_page.menu_name|default:"traditionelle asiatische Spielkultur"}}{% endblock %}</title> <title>Kasu - {% block title %}{{ current_top_page.menu_name|default:"traditionelle asiatische Spielkultur"}}{% endblock %}</title>

View File

@@ -20,8 +20,8 @@
</label> </label>
{{form.comment}} {{form.comment}}
<p class="buttonbar"> <p class="buttonbar">
<button type="submit" name="preview"><img src="{{ STATIC_URL }}icons/comment_edit.png" alt="{% trans "Preview" %}" /> {% trans "Preview" %}</button> <button type="submit" name="preview"><img src="{{ STATIC_URL }}icons/comment_edit.png" alt="{% trans 'Preview' %}" /> {% trans "Preview" %}</button>
<button type="submit" name="submit"><img src="{{ STATIC_URL }}icons/comment_add.png" alt="{% trans "Post" %}" /> {% trans "Post" %}</button> <button type="submit" name="submit"><img src="{{ STATIC_URL }}icons/comment_add.png" alt="{% trans 'Post' %}" /> {% trans "Post" %}</button>
</p> </p>
{% else %} {% else %}
<label class="field_name" for="id_comment"> <label class="field_name" for="id_comment">

View File

@@ -27,7 +27,7 @@ you can fill out our registration form.</p>
{% endblocktrans %} {% endblocktrans %}
<p class="more_link"> <p class="more_link">
<a href="{% url 'membership-register' %}" class="button"> <a href="{% url 'membership-register' %}" class="button">
<img src="{{STATIC_URL}}icons/user_add.png" alt="{%trans "register"%}"/> <img src="{{STATIC_URL}}icons/user_add.png" alt="{%trans 'register' %}"/>
{%trans "register"%}</a></p> {%trans "register"%}</a></p>
</div> </div>
@@ -44,7 +44,7 @@ you can fill out our registration form.</p>
<p><a href="{% url 'password_reset' %}">{% trans 'Forgot your Password?'%}</a></p> <p><a href="{% url 'password_reset' %}">{% trans 'Forgot your Password?'%}</a></p>
<div class="buttonbar"> <div class="buttonbar">
<button type="submit"> <button type="submit">
<img src="{{STATIC_URL}}icons/lock_break.png" alt="{% trans "Login" %}" /> {% trans "Login" %} <img src="{{STATIC_URL}}icons/lock_break.png" alt="{% trans 'Login' %}" /> {% trans 'Login' %}
</button></div> </button></div>
</fieldset> </fieldset>

View File

@@ -19,7 +19,7 @@
{% include 'form.html' %} {% include 'form.html' %}
<div class="buttonbar"> <div class="buttonbar">
<button type="submit"> <button type="submit">
<img src="{{STATIC_URL}}icons/lock_break.png" alt="{% trans "Login" %}" /> {% trans "Change Password" %} <img src="{{STATIC_URL}}icons/lock_break.png" alt="{% trans 'Login' %}" /> {% trans "Change Password" %}
</button> </button>
</div> </div>
</form> </form>

View File

@@ -1,8 +1,8 @@
''' """
Created on 28.09.2011 Created on 28.09.2011
@author: christian @author: christian
''' """
from .countries import COUNTRIES from .countries import COUNTRIES
from .html_cleaner import HtmlCleaner from .html_cleaner import HtmlCleaner
from .massmailer import MassMailer from .massmailer import MassMailer

View File

@@ -1,8 +1,8 @@
''' """
Created on 24.11.2011 Created on 24.11.2011
@author: christian @author: christian
''' """
from django import forms from django import forms
import datetime import datetime

View File

@@ -1,8 +1,8 @@
''' """
Created on 08.05.2011 Created on 08.05.2011
@author: christian @author: christian
''' """
import re import re
from django.conf import settings from django.conf import settings
@@ -17,10 +17,10 @@ from . import widgets
class Html5Mixin(object): class Html5Mixin(object):
def widget_attrs(self, widget): def widget_attrs(self, widget):
''' """
Overwrites the standard Widget Attributes to add some HTML5 Stuff Overwrites the standard Widget Attributes to add some HTML5 Stuff
:param widget: A Widget Object :param widget: A Widget Object
''' """
attrs = super(Html5Mixin, self).widget_attrs(widget) attrs = super(Html5Mixin, self).widget_attrs(widget)
if self.required and not isinstance(widget, widgets.CheckboxInput): if self.required and not isinstance(widget, widgets.CheckboxInput):
attrs['required'] = 'required' attrs['required'] = 'required'
@@ -199,9 +199,8 @@ class ReCaptchaField(django.forms.fields.CharField):
self.required = True self.required = True
super(ReCaptchaField, self).__init__(*args, **kwargs) super(ReCaptchaField, self).__init__(*args, **kwargs)
def _check_recaptcha(self, challenge_value, response_value, \ def _check_recaptcha(self, challenge_value, response_value, remote_ip):
remote_ip={}): """
'''
Submits a reCAPTCHA request for verification. Submits a reCAPTCHA request for verification.
Returns RecaptchaResponse for the request Returns RecaptchaResponse for the request
@@ -209,7 +208,7 @@ class ReCaptchaField(django.forms.fields.CharField):
@param response_value: value of recaptcha_response_field @param response_value: value of recaptcha_response_field
@param remoteip -- the user's ip address @param remoteip -- the user's ip address
''' """
import urllib import urllib
import urllib2 import urllib2
private_key = settings.RECAPTCHA_PRIVATE_KEY private_key = settings.RECAPTCHA_PRIVATE_KEY

View File

@@ -1,8 +1,8 @@
''' """
Created on 08.05.2011 Created on 08.05.2011
@author: christian @author: christian
''' """
from django.db import models from django.db import models
from django.db.models import ForeignKey, Model, SET_NULL # @UnusedImport from django.db.models import ForeignKey, Model, SET_NULL # @UnusedImport
from django.db.models import SET_DEFAULT, ManyToManyField # @UnusedImport from django.db.models import SET_DEFAULT, ManyToManyField # @UnusedImport

View File

@@ -1,8 +1,8 @@
''' """
Created on 05.08.2011 Created on 05.08.2011
@author: christian @author: christian
''' """
from django.http import Http404 from django.http import Http404
from . import registry from . import registry

View File

@@ -1,8 +1,8 @@
''' """
Created on 08.05.2011 Created on 08.05.2011
@author: christian @author: christian
''' """
from django.conf import settings from django.conf import settings
from django.forms import widgets from django.forms import widgets
from django.forms.util import flatatt from django.forms.util import flatatt
@@ -119,9 +119,9 @@ class RangeInput(widgets.TextInput):
class ReCaptchaInput(widgets.Widget): class ReCaptchaInput(widgets.Widget):
''' """
Der HTML Code von Googles ReCaptcha als Form Widget Der HTML Code von Googles ReCaptcha als Form Widget
''' """
recaptcha_challenge_name = 'recaptcha_challenge_field' recaptcha_challenge_name = 'recaptcha_challenge_field'
recaptcha_response_name = 'recaptcha_response_field' recaptcha_response_name = 'recaptcha_response_field'

View File

@@ -1,8 +1,8 @@
''' """
Created on 19.10.2011 Created on 19.10.2011
@author: christian @author: christian
''' """
from BeautifulSoup import BeautifulSoup from BeautifulSoup import BeautifulSoup
@@ -46,10 +46,10 @@ class HtmlCleaner(object):
self.clean_attributes(tag) self.clean_attributes(tag)
def clean_html(self, fragment=''): def clean_html(self, fragment=''):
''' """
Reparses and cleans the html from XSS Attacks until it stops changing. Reparses and cleans the html from XSS Attacks until it stops changing.
@param fragment: @param fragment:
''' """
while True: while True:
soup = BeautifulSoup(fragment) soup = BeautifulSoup(fragment)
self.tag_removed = False self.tag_removed = False

View File

@@ -653,17 +653,17 @@ class vDDDLists:
self.dts = vDDD self.dts = vDDD
def ical(self): def ical(self):
''' """
Generates the text string in the iCalendar format. Generates the text string in the iCalendar format.
''' """
dts_ical = [dt.ical() for dt in self.dts] dts_ical = [dt.ical() for dt in self.dts]
return ",".join(dts_ical) return ",".join(dts_ical)
def from_ical(ical): def from_ical(ical):
''' """
Parses the list of data formats from ical text format. Parses the list of data formats from ical text format.
@param ical: ical text format @param ical: ical text format
''' """
out = [] out = []
ical_dates = ical.split(",") ical_dates = ical.split(",")
for ical_dt in ical_dates: for ical_dt in ical_dates:

View File

@@ -1,8 +1,8 @@
''' """
Created on 06.06.2011 Created on 06.06.2011
@author: christian @author: christian
''' """
import fnmatch import fnmatch
from optparse import make_option from optparse import make_option
import os import os
@@ -15,9 +15,9 @@ from django.utils.translation import ugettext as _
class Command(BaseCommand): class Command(BaseCommand):
''' """
classdocs classdocs
''' """
can_import_settings = True can_import_settings = True
help = _("Reads raw CSS from stdin, and writes compressed CSS to stdout.") help = _("Reads raw CSS from stdin, and writes compressed CSS to stdout.")
option_list = BaseCommand.option_list + ( option_list = BaseCommand.option_list + (

View File

@@ -1,8 +1,8 @@
''' """
Created on 06.06.2011 Created on 06.06.2011
@author: christian @author: christian
''' """
import fnmatch import fnmatch
import os import os
@@ -14,9 +14,9 @@ import jsmin
class Command(BaseCommand): class Command(BaseCommand):
''' """
classdocs classdocs
''' """
can_import_settings = True can_import_settings = True
help = _("Reads raw CSS from stdin, and writes compressed CSS to stdout.") help = _("Reads raw CSS from stdin, and writes compressed CSS to stdout.")

View File

@@ -1,8 +1,8 @@
''' """
Created on 06.06.2011 Created on 06.06.2011
@author: christian @author: christian
''' """
from django.conf import settings from django.conf import settings
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
@@ -13,9 +13,9 @@ from scss import parser
class Command(BaseCommand): class Command(BaseCommand):
''' """
classdocs classdocs
''' """
can_import_settings = True can_import_settings = True
help = _("Compile SCSS rules.") help = _("Compile SCSS rules.")

View File

@@ -6,11 +6,11 @@ from django.template import loader, Context
class MassMailer(object): class MassMailer(object):
''' """
This Class will send E-Mails via an SMTP Connection to multiple recipients. This Class will send E-Mails via an SMTP Connection to multiple recipients.
Each E-Mail will be send individually and can be personalized. Each E-Mail will be send individually and can be personalized.
It will be send as HTML and Plain-Text Message. It will be send as HTML and Plain-Text Message.
''' """
context = {} context = {}
headers = {} headers = {}
subject = None subject = None
@@ -83,9 +83,9 @@ class MassMailer(object):
self.headers[name] = value self.headers[name] = value
def send(self): def send(self):
''' """
Process the E-Mails and send them Process the E-Mails and send them
''' """
self.process_mails() self.process_mails()
if len(self.mail_queue) == 0: if len(self.mail_queue) == 0:
self.log.info('No recipients for eMail "%s", bye!', self.subject) self.log.info('No recipients for eMail "%s", bye!', self.subject)

View File

@@ -1,17 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
Created on 23.05.2011 Created on 23.05.2011
@author: christian @author: christian
''' """
from django.utils.html import strip_spaces_between_tags from django.utils.html import strip_spaces_between_tags
class CompressHtmlMiddleware(object): class CompressHtmlMiddleware(object):
''' """
This Middleware compresses the HTML Output at the End. It strips the Spaces This Middleware compresses the HTML Output at the End. It strips the Spaces
between Tags, an at the beginning and the end of the content. between Tags, an at the beginning and the end of the content.
''' """
def process_response(self, request, response): def process_response(self, request, response):
if 'text/html' in response['Content-Type']: if 'text/html' in response['Content-Type']:

View File

@@ -60,7 +60,7 @@ class PermissionRequiredMixin(object):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
# Verify class settings # Verify class settings
if self.permission_required == None or len(self.permission_required.split(".")) != 2: if self.permission_required is None or len(self.permission_required.split(".")) != 2:
raise ImproperlyConfigured("'PermissionRequiredMixin' requires 'permission_required' attribute to be set.") raise ImproperlyConfigured("'PermissionRequiredMixin' requires 'permission_required' attribute to be set.")
has_permission = request.user.has_perm(self.permission_required) has_permission = request.user.has_perm(self.permission_required)

View File

@@ -1,9 +1,9 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
''' """
Created on 25.11.2013 Created on 25.11.2013
@author: christian @author: christian
''' """
from django import template from django import template
from django.conf import settings from django.conf import settings
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe