add a latest method to query the latest x events
This commit is contained in:
@@ -31,6 +31,10 @@ class EventManager(models.Manager):
|
|||||||
"""Returns all past events."""
|
"""Returns all past events."""
|
||||||
return self.filter(start__lt=now())
|
return self.filter(start__lt=now())
|
||||||
|
|
||||||
|
def latest(self, limit=None):
|
||||||
|
result = self.filter(start__lt=now()).order_by('-start', '-end')
|
||||||
|
return result[0:limit] if limit else result
|
||||||
|
|
||||||
def upcoming(self, limit=None):
|
def upcoming(self, limit=None):
|
||||||
"""Returns the next 'limit' upcoming events.
|
"""Returns the next 'limit' upcoming events.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
"""Mixins for Events."""
|
"""Mixins for Events."""
|
||||||
|
from django.http import Http404
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
@@ -9,7 +11,6 @@ class EventArchiveMixin(object):
|
|||||||
date_field = 'start'
|
date_field = 'start'
|
||||||
make_object_list = True
|
make_object_list = True
|
||||||
model = models.Event
|
model = models.Event
|
||||||
ordering = ('start', 'end')
|
|
||||||
paginate_by = 15
|
paginate_by = 15
|
||||||
template_name = 'events/event_archive.html'
|
template_name = 'events/event_archive.html'
|
||||||
|
|
||||||
@@ -40,3 +41,16 @@ class EventDetailMixin(object):
|
|||||||
elif hasattr(self, 'object') and hasattr(self.object, 'event'):
|
elif hasattr(self, 'object') and hasattr(self.object, 'event'):
|
||||||
context['event'] = self.object.event
|
context['event'] = self.object.event
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""set event attribute from the URL kwarg event and
|
||||||
|
load all related objects from the set model.
|
||||||
|
|
||||||
|
:return: a django QuerySets
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.event = models.Event.objects.get(pk=self.kwargs['event'])
|
||||||
|
queryset = self.model.objects.filter(event=self.event)
|
||||||
|
except models.Event.DoesNotExist:
|
||||||
|
raise Http404(_('Event does not exist'))
|
||||||
|
return queryset.prefetch_related()
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ class DeleteEventPhoto(PermissionRequiredMixin, mixins.EventDetailMixin,
|
|||||||
class EventArchiveIndex(mixins.EventArchiveMixin, generic.ArchiveIndexView):
|
class EventArchiveIndex(mixins.EventArchiveMixin, generic.ArchiveIndexView):
|
||||||
"""Index of the event archive, displays the upcoming events first."""
|
"""Index of the event archive, displays the upcoming events first."""
|
||||||
allow_empty = True
|
allow_empty = True
|
||||||
ordering = ('-start', '-end')
|
|
||||||
|
|
||||||
|
|
||||||
class EventArchiveMonth(mixins.EventArchiveMixin, generic.MonthArchiveView):
|
class EventArchiveMonth(mixins.EventArchiveMixin, generic.MonthArchiveView):
|
||||||
@@ -73,7 +72,7 @@ class EventForm(PermissionRequiredMixin, mixins.EventDetailMixin,
|
|||||||
if self.kwargs.get('pk') else models.Event()
|
if self.kwargs.get('pk') else models.Event()
|
||||||
|
|
||||||
|
|
||||||
class EventGallery(mixins.EventDetailMixin, generic.ListView):
|
class EventGallery(generic.ListView):
|
||||||
"""Display a overview of all event photo albums."""
|
"""Display a overview of all event photo albums."""
|
||||||
template_name = 'events/photo_gallery.html'
|
template_name = 'events/photo_gallery.html'
|
||||||
queryset = models.Event.objects.filter(
|
queryset = models.Event.objects.filter(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class HanchanManager(models.Manager):
|
|||||||
"""
|
"""
|
||||||
use_for_related_fields = True
|
use_for_related_fields = True
|
||||||
|
|
||||||
def confirmed_hanchans(self, user=None, since=None, until=None, **filter_args):
|
def confirmed(self, user=None, since=None, until=None, **filter_args):
|
||||||
""" Return all valid and confirmed Hanchans.
|
""" Return all valid and confirmed Hanchans.
|
||||||
|
|
||||||
:param user: Only return Hanchans where this user participated.
|
:param user: Only return Hanchans where this user participated.
|
||||||
@@ -85,7 +85,7 @@ class HanchanManager(models.Manager):
|
|||||||
season = season or until.year
|
season = season or until.year
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
season = date.today().year
|
season = date.today().year
|
||||||
return self.confirmed_hanchans(user=user, season=season, until=until)
|
return self.confirmed(user=user, season=season, until=until)
|
||||||
|
|
||||||
def user_hanchans(self, user, since=None, until=None, **filter_args):
|
def user_hanchans(self, user, since=None, until=None, **filter_args):
|
||||||
"""Return all Hanchans where a specific user has participated.
|
"""Return all Hanchans where a specific user has participated.
|
||||||
@@ -108,7 +108,7 @@ class HanchanManager(models.Manager):
|
|||||||
[hanchan.get_playerdata(user) for hanchan in queryset]
|
[hanchan.get_playerdata(user) for hanchan in queryset]
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def unconfirmed_hanchans(self, user=None, **filter_args):
|
def unconfirmed(self, user=None, **filter_args):
|
||||||
""" Return all Hanchans that have been set to unconfirmed.
|
""" Return all Hanchans that have been set to unconfirmed.
|
||||||
|
|
||||||
:param user: Only return Hanchans where this user participated.
|
:param user: Only return Hanchans where this user participated.
|
||||||
|
|||||||
18
src/mahjong_ranking/mixins.py
Normal file
18
src/mahjong_ranking/mixins.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from datetime import date
|
||||||
|
from .models import Hanchan, SeasonRanking
|
||||||
|
from events.models import Event
|
||||||
|
|
||||||
|
|
||||||
|
class MahjongMixin(object):
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(MahjongMixin, self).get_context_data(**kwargs)
|
||||||
|
try:
|
||||||
|
context['season'] = self.season
|
||||||
|
context['season_start'] = date(year=self.season, month=1, day=1)
|
||||||
|
context['season_end'] = date(year=self.season, month=12, day=31)
|
||||||
|
context['season_list'] = SeasonRanking.objects.season_list
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
context['latest_hanchan_list'] = Hanchan.objects.confirmed()[:3]
|
||||||
|
context['latest_event_list'] = Event.objects.latest(limit=3)
|
||||||
|
return context
|
||||||
@@ -56,7 +56,7 @@ class EventRanking(models.Model):
|
|||||||
)
|
)
|
||||||
sum_placement = 0.0
|
sum_placement = 0.0
|
||||||
sum_score = 0.0
|
sum_score = 0.0
|
||||||
event_hanchans = Hanchan.objects.confirmed_hanchans(
|
event_hanchans = Hanchan.objects.confirmed(
|
||||||
user=self.user_id,
|
user=self.user_id,
|
||||||
event=self.event_id
|
event=self.event_id
|
||||||
)
|
)
|
||||||
@@ -441,7 +441,7 @@ class KyuDanRanking(models.Model):
|
|||||||
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.
|
||||||
"""
|
"""
|
||||||
valid_hanchans = Hanchan.objects.confirmed_hanchans(user=self.user)
|
valid_hanchans = Hanchan.objects.confirmed(user=self.user)
|
||||||
valid_hanchans = valid_hanchans.order_by('start')
|
valid_hanchans = valid_hanchans.order_by('start')
|
||||||
if since and self.last_hanchan_date and since < self.last_hanchan_date:
|
if since and self.last_hanchan_date and since < self.last_hanchan_date:
|
||||||
force_recalc = True
|
force_recalc = True
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class KyuDanTest(TestCase):
|
|||||||
|
|
||||||
for ranking in KyuDanRanking.objects.all():
|
for ranking in KyuDanRanking.objects.all():
|
||||||
original = {a: getattr(ranking, a) for a in self.equal_attrs}
|
original = {a: getattr(ranking, a) for a in self.equal_attrs}
|
||||||
confirmed_hanchans = Hanchan.objects.confirmed_hanchans(
|
confirmed_hanchans = Hanchan.objects.confirmed(
|
||||||
user=ranking.user,
|
user=ranking.user,
|
||||||
since=ranking.legacy_date
|
since=ranking.legacy_date
|
||||||
)
|
)
|
||||||
@@ -86,7 +86,7 @@ class KyuDanTest(TestCase):
|
|||||||
'dan_points': ranking.legacy_dan_points or 0,
|
'dan_points': ranking.legacy_dan_points or 0,
|
||||||
'kyu_points': ranking.legacy_kyu_points or 0
|
'kyu_points': ranking.legacy_kyu_points or 0
|
||||||
}
|
}
|
||||||
confirmed_hanchans = Hanchan.objects.confirmed_hanchans(
|
confirmed_hanchans = Hanchan.objects.confirmed(
|
||||||
user=ranking.user,
|
user=ranking.user,
|
||||||
since=ranking.legacy_date
|
since=ranking.legacy_date
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ 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 events.models import Event
|
|
||||||
from events.mixins import EventDetailMixin
|
from events.mixins import EventDetailMixin
|
||||||
from . import forms, models
|
from . import forms, models
|
||||||
|
from .mixins import MahjongMixin
|
||||||
|
|
||||||
kyu_dan_order = {
|
KYU_DAN_ORDER = { # map sort URL args to Django ORM order_by args
|
||||||
'+full_name': ('user__last_name', 'user__first_name'),
|
'+full_name': ('user__last_name', 'user__first_name'),
|
||||||
'-full_name': ('-user__last_name', '-user__first_name'),
|
'-full_name': ('-user__last_name', '-user__first_name'),
|
||||||
'+hanchan_count': ('hanchan_count',),
|
'+hanchan_count': ('hanchan_count',),
|
||||||
@@ -31,16 +31,17 @@ kyu_dan_order = {
|
|||||||
|
|
||||||
class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin,
|
class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin,
|
||||||
generic.DeleteView):
|
generic.DeleteView):
|
||||||
"""
|
"""Deletes a Hanchan if confimration has been answerd with 'yes'."""
|
||||||
Fragt zuerst nach, ob die Hanchan wirklich gelöscht werden soll.
|
|
||||||
Wir die Frage mit "Ja" beantwortet, wird die die Hanchan gelöscht.
|
|
||||||
"""
|
|
||||||
form_class = forms.HanchanForm
|
form_class = forms.HanchanForm
|
||||||
model = models.Hanchan
|
model = models.Hanchan
|
||||||
permission_required = 'mahjong_ranking.delete_hanchan'
|
permission_required = 'mahjong_ranking.delete_hanchan'
|
||||||
pk_url_kwarg = 'hanchan'
|
pk_url_kwarg = 'hanchan'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
"""
|
||||||
|
Return to the HachanList of the event form the deleted hanchan.
|
||||||
|
:return: URL of the EventHanchanList for the event
|
||||||
|
"""
|
||||||
return reverse('event-hanchan-list',
|
return reverse('event-hanchan-list',
|
||||||
kwargs={'event': self.object.event.pk})
|
kwargs={'event': self.object.event.pk})
|
||||||
|
|
||||||
@@ -48,32 +49,30 @@ class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin,
|
|||||||
class HanchanForm(SuccessMessageMixin, EventDetailMixin,
|
class HanchanForm(SuccessMessageMixin, EventDetailMixin,
|
||||||
PermissionRequiredMixin, generic.UpdateView):
|
PermissionRequiredMixin, generic.UpdateView):
|
||||||
"""
|
"""
|
||||||
Ein Formular um neue Hanchans anzulegen, bzw. eine bestehende zu
|
A Form to add a new or edit an existing Hanchan.
|
||||||
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'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = generic.UpdateView.get_context_data(self, **kwargs)
|
|
||||||
context['event'] = self.event
|
|
||||||
return context
|
|
||||||
|
|
||||||
def get_form_class(self):
|
def get_form_class(self):
|
||||||
"""
|
"""
|
||||||
Users with edit Persmission will see the AdminForm to confirm
|
Users with hanchan edit persmission can also un-/confirm hanchans.
|
||||||
unconfirmed Hanchans.
|
:return: forms.HanchanForm, or forms.HanchanAdminForm
|
||||||
"""
|
"""
|
||||||
if self.request.user.has_perm('mahjong_ranking.change_hanchan'):
|
return forms.HanchanAdminForm if self.request.user.has_perm(
|
||||||
return forms.HanchanAdminForm
|
'mahjong_ranking.change_hanchan') else forms.HanchanForm
|
||||||
else:
|
|
||||||
return forms.HanchanForm
|
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
|
"""
|
||||||
|
load the hanchan form the db, or create a new one with the event set.
|
||||||
|
Also sets the event attribute.
|
||||||
|
:param queryset:
|
||||||
|
:return: models.Hanchan object
|
||||||
|
"""
|
||||||
if self.kwargs.get('hanchan') and self.request.user.has_perm(
|
if self.kwargs.get('hanchan') and self.request.user.has_perm(
|
||||||
'mahjong_ranking.change_hanchan'):
|
'mahjong_ranking.change_hanchan'):
|
||||||
hanchan = models.Hanchan.objects.get(id=self.kwargs['hanchan'])
|
hanchan = self.model.objects.get(id=self.kwargs['hanchan'])
|
||||||
self.event = hanchan.event
|
self.event = hanchan.event
|
||||||
elif self.kwargs.get('event'):
|
elif self.kwargs.get('event'):
|
||||||
self.event = models.Event.objects.get(id=self.kwargs['event'])
|
self.event = models.Event.objects.get(id=self.kwargs['event'])
|
||||||
@@ -94,6 +93,11 @@ class HanchanForm(SuccessMessageMixin, EventDetailMixin,
|
|||||||
return reverse('add-hanchan-form', kwargs={'event': self.event.pk})
|
return reverse('add-hanchan-form', kwargs={'event': self.event.pk})
|
||||||
|
|
||||||
def get_success_message(self, cleaned_data):
|
def get_success_message(self, cleaned_data):
|
||||||
|
"""
|
||||||
|
Get the right sucsess message for the django notification subsystem.
|
||||||
|
:param cleaned_data:
|
||||||
|
:return: Sucsess message
|
||||||
|
"""
|
||||||
if self.kwargs.get('hanchan'):
|
if self.kwargs.get('hanchan'):
|
||||||
return _('%s has been updated successfully.') % self.object
|
return _('%s has been updated successfully.') % self.object
|
||||||
else:
|
else:
|
||||||
@@ -103,72 +107,36 @@ class HanchanForm(SuccessMessageMixin, EventDetailMixin,
|
|||||||
|
|
||||||
|
|
||||||
class EventHanchanList(EventDetailMixin, generic.ListView):
|
class EventHanchanList(EventDetailMixin, generic.ListView):
|
||||||
"""
|
"List all hanchans played on a given event."
|
||||||
Auflistung aller Hanchan die während der Veranstaltung gespielt wurden.
|
|
||||||
"""
|
|
||||||
model = models.Hanchan
|
model = models.Hanchan
|
||||||
template_name = 'mahjong_ranking/eventhanchan_list.html'
|
template_name = 'mahjong_ranking/eventhanchan_list.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
try:
|
|
||||||
self.event = models.Event.objects.get(pk=self.kwargs['event'])
|
|
||||||
queryset = models.Hanchan.objects.filter(event=self.event)
|
|
||||||
queryset = queryset.order_by('start')
|
|
||||||
return queryset
|
|
||||||
except models.Event.DoesNotExist:
|
|
||||||
raise django.http.Http404(_('Event does not exist'))
|
|
||||||
|
|
||||||
|
|
||||||
class EventRankingList(EventDetailMixin, generic.ListView):
|
class EventRankingList(EventDetailMixin, generic.ListView):
|
||||||
"""
|
"""Display the event ranking for the given event."""
|
||||||
Anzeige des Eventrankings, daß erstellt wurde falls der Termin als internes
|
|
||||||
Turnier markiert wurde.
|
|
||||||
"""
|
|
||||||
model = models.EventRanking
|
model = models.EventRanking
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
try:
|
|
||||||
self.event = models.Event.objects.get(pk=self.kwargs['event'])
|
|
||||||
queryset = models.EventRanking.objects.filter(event=self.event)
|
|
||||||
return queryset.prefetch_related()
|
|
||||||
except models.Event.DoesNotExist:
|
|
||||||
raise django.http.Http404(_('Event does not exist'))
|
|
||||||
|
|
||||||
|
|
||||||
class MahjongMixin(object):
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(MahjongMixin, self).get_context_data(**kwargs)
|
|
||||||
try:
|
|
||||||
context['season'] = self.season
|
|
||||||
context['season_start'] = date(year=self.season, month=1, day=1)
|
|
||||||
context['season_end'] = date(year=self.season, month=12, day=31)
|
|
||||||
context['season_list'] = models.SeasonRanking.objects.season_list
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
context[
|
|
||||||
'latest_hanchan_list'] = \
|
|
||||||
models.Hanchan.objects.confirmed_hanchans()[
|
|
||||||
:3]
|
|
||||||
context['latest_event_list'] = Event.objects.upcoming(limit=3)
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class KyuDanRankingList(MahjongMixin, generic.ListView):
|
class KyuDanRankingList(MahjongMixin, generic.ListView):
|
||||||
"""
|
"""List all Players with an Kyu or Dan score. """
|
||||||
Anzeige aller Spiele mit ihrem Kyu bzw Dan Grad.
|
|
||||||
"""
|
|
||||||
default_order = '-score'
|
default_order = '-score'
|
||||||
order_by = ''
|
order_by = ''
|
||||||
paginate_by = 25
|
paginate_by = 25
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.order_by = kyu_dan_order[
|
"""Set the order_by settings, revert to default_order if necessary."""
|
||||||
|
self.order_by = KYU_DAN_ORDER[
|
||||||
kwargs.get('order_by', self.default_order)
|
kwargs.get('order_by', self.default_order)
|
||||||
]
|
]
|
||||||
return generic.ListView.dispatch(self, request, *args, **kwargs)
|
return super(KyuDanRankingList, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = models.KyuDanRanking.objects.all().order_by(*self.order_by)
|
queryset = models.KyuDanRanking.objects.filter(
|
||||||
|
hanchan_count__gt=0).order_by(*self.order_by)
|
||||||
return queryset.select_related()
|
return queryset.select_related()
|
||||||
|
|
||||||
|
|
||||||
@@ -224,14 +192,15 @@ class PlayerDanScore(PlayerScore):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
kyu_dan_ranking = models.KyuDanRanking.objects.get(user=self.user)
|
kyu_dan_ranking = models.KyuDanRanking.objects.get(user=self.user)
|
||||||
return models.Hanchan.objects.dan_hanchans(user=self.user, since=kyu_dan_ranking.legacy_date)
|
return models.Hanchan.objects.dan_hanchans(user=self.user,
|
||||||
|
since=kyu_dan_ranking.legacy_date)
|
||||||
|
|
||||||
|
|
||||||
class PlayerInvalidScore(PlayerScore):
|
class PlayerInvalidScore(PlayerScore):
|
||||||
template_name = 'mahjong_ranking/player_invalid_score.html'
|
template_name = 'mahjong_ranking/player_invalid_score.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return models.Hanchan.objects.unconfirmed_hanchans(user=self.user)
|
return models.Hanchan.objects.unconfirmed(user=self.user)
|
||||||
|
|
||||||
|
|
||||||
class PlayerKyuScore(PlayerScore):
|
class PlayerKyuScore(PlayerScore):
|
||||||
|
|||||||
Reference in New Issue
Block a user