add a latest method to query the latest x events

This commit is contained in:
2017-11-23 14:15:12 +01:00
parent 5ad628f33a
commit bf12060c3b
8 changed files with 81 additions and 77 deletions

View File

@@ -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.

View File

@@ -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()

View File

@@ -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(

View File

@@ -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.

View 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

View File

@@ -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

View File

@@ -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
) )

View File

@@ -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):