admin.py 7.3 KB
Newer Older
Thom Wiggers's avatar
Thom Wiggers committed
1
2
3
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.http import HttpResponseRedirect
4
from django.template.defaultfilters import date as _date
5
from django.urls import reverse
Thom Wiggers's avatar
Thom Wiggers committed
6
7
from django.utils import timezone
from django.utils.html import format_html
8
from django.utils.http import is_safe_url
Thom Wiggers's avatar
Thom Wiggers committed
9
from django.utils.translation import ugettext_lazy as _
10

11
from events import services
Thom Wiggers's avatar
Thom Wiggers committed
12
from members.models import Member
13
from pizzas.models import PizzaEvent
14
from utils.translation import TranslatedModelAdmin
15
from . import forms, models
Thom Wiggers's avatar
Thom Wiggers committed
16

Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
17

18
class DoNextModelAdmin(TranslatedModelAdmin):
Thom Wiggers's avatar
Thom Wiggers committed
19

20
21
22
23
24
25
    def _do_next(self, request, response):
        if 'next' in request.GET and is_safe_url(request.GET['next']):
            return HttpResponseRedirect(request.GET['next'])
        else:
            return response

Thom Wiggers's avatar
Thom Wiggers committed
26
27
    def response_add(self, request, obj):
        res = super().response_add(request, obj)
28
        return self._do_next(request, res)
Thom Wiggers's avatar
Thom Wiggers committed
29
30
31

    def response_change(self, request, obj):
        res = super().response_change(request, obj)
32
        return self._do_next(request, res)
Thom Wiggers's avatar
Thom Wiggers committed
33
34
35


class RegistrationInformationFieldInline(admin.StackedInline):
36
    form = forms.RegistrationInformationFieldForm
Thom Wiggers's avatar
Thom Wiggers committed
37
38
39
40
41
42
    extra = 0
    model = models.RegistrationInformationField
    ordering = ('_order',)

    radio_fields = {'type': admin.VERTICAL}

43
44
45
46
47
48
49
    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj, **kwargs)
        if obj is not None:
            count = obj.registrationinformationfield_set.count()
            formset.form.declared_fields['order'].initial = count
        return formset

Thom Wiggers's avatar
Thom Wiggers committed
50

51
52
53
54
55
56
class PizzaEventInline(admin.StackedInline):
    model = PizzaEvent
    extra = 0
    max_num = 1


Thom Wiggers's avatar
Thom Wiggers committed
57
58
@admin.register(models.Event)
class EventAdmin(DoNextModelAdmin):
59
    inlines = (RegistrationInformationFieldInline, PizzaEventInline,)
60
    fields = ('title', 'description', 'start', 'end', 'organiser', 'category',
61
              'registration_start', 'registration_end', 'cancel_deadline',
62
              'send_cancel_email', 'location', 'map_location', 'price', 'fine',
63
              'max_participants', 'no_registration_message', 'published')
64
    list_display = ('overview_link', 'event_date', 'registration_date',
65
66
                    'num_participants', 'organiser', 'category', 'published',
                    'edit_link')
Thom Wiggers's avatar
Thom Wiggers committed
67
    list_display_links = ('edit_link',)
68
    list_filter = ('start', 'published', 'category')
Thom Wiggers's avatar
Thom Wiggers committed
69
70
71
72
73
74
75
76
77
78
79
    actions = ('make_published', 'make_unpublished')
    date_hierarchy = 'start'
    search_fields = ('title', 'description')
    prepopulated_fields = {'map_location': ('location',)}

    def overview_link(self, obj):
        return format_html('<a href="{link}">{title}</a>',
                           link=reverse('events:admin-details',
                                        kwargs={'event_id': obj.pk}),
                           title=obj.title)

80
    def has_change_permission(self, request, event=None):
81
        if (event is not None and
82
                not services.is_organiser(request.member, event)):
83
            return False
84
85
        return super().has_change_permission(request, event)

86
    def event_date(self, obj):
87
        event_date = timezone.make_naive(obj.start)
88
89
90
91
        return _date(event_date, "l d b Y, G:i")
    event_date.short_description = _('Event Date')

    def registration_date(self, obj):
92
93
94
95
96
        if obj.registration_start is not None:
            start_date = timezone.make_naive(obj.registration_start)
        else:
            start_date = obj.registration_start

97
        return _date(start_date, "l d b Y, G:i")
Milan van Stiphout's avatar
Milan van Stiphout committed
98
    registration_date.short_description = _('Registration Start')
99

Thom Wiggers's avatar
Thom Wiggers committed
100
101
102
103
104
105
106
    def edit_link(self, obj):
        return _('Edit')
    edit_link.short_description = ''

    def num_participants(self, obj):
        """Pretty-print the number of participants"""
        num = (obj.registration_set
Joren Vrancken's avatar
Joren Vrancken committed
107
               .exclude(date_cancelled__lt=timezone.now()).count())
Thom Wiggers's avatar
Thom Wiggers committed
108
109
110
111
112
113
        if not obj.max_participants:
            return '{}/∞'.format(num)
        return '{}/{}'.format(num, obj.max_participants)
    num_participants.short_description = _('Number of participants')

    def make_published(self, request, queryset):
114
        self._change_published(request, queryset, True)
Thom Wiggers's avatar
Thom Wiggers committed
115
116
117
    make_published.short_description = _('Publish selected events')

    def make_unpublished(self, request, queryset):
118
        self._change_published(request, queryset, False)
Thom Wiggers's avatar
Thom Wiggers committed
119
120
    make_unpublished.short_description = _('Unpublish selected events')

121
122
    @staticmethod
    def _change_published(request, queryset, published):
123
124
125
126
        if not request.user.is_superuser:
            queryset = queryset.filter(
                organiser__in=request.member.get_committees())
        queryset.update(published=published)
127

Thom Wiggers's avatar
Thom Wiggers committed
128
129
130
131
    def save_formset(self, request, form, formset, change):
        """Save formsets with their order"""
        formset.save()

132
133
134
135
        informationfield_forms = (
            x for x in formset.forms if
            isinstance(x, forms.RegistrationInformationFieldForm)
        )
Thom Wiggers's avatar
Thom Wiggers committed
136
137
        form.instance.set_registrationinformationfield_order([
            f.instance.pk
138
            for f in sorted(informationfield_forms,
Thom Wiggers's avatar
Thom Wiggers committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
                            key=lambda x: (x.cleaned_data['order'],
                                           x.instance.pk))
        ])
        form.instance.save()

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        field = super().formfield_for_dbfield(db_field, request, **kwargs)
        if db_field.name == 'organiser':
            # Disable add/change/delete buttons
            field.widget.can_add_related = False
            field.widget.can_change_related = False
            field.widget.can_delete_related = False
        return field

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'organiser':
            # Use custom queryset for organiser field
156
            # Only get the current active committees the user is a member of
157
158
159
            if not (request.user.is_superuser or
                    request.user.has_perm('events.override_organiser')):
                kwargs['queryset'] = request.member.get_committees()
Thom Wiggers's avatar
Thom Wiggers committed
160
161
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

162
163
164
165
166
    def get_actions(self, request):
        actions = super(EventAdmin, self).get_actions(request)
        del actions['delete_selected']
        return actions

Thom Wiggers's avatar
Thom Wiggers committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

@admin.register(models.Registration)
class RegistrationAdmin(DoNextModelAdmin):
    """Custom admin for registrations"""

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        field = super().formfield_for_dbfield(db_field, request, **kwargs)
        if db_field.name in ('event', 'member'):
            # Disable add/change/delete buttons
            field.widget.can_add_related = False
            field.widget.can_change_related = False
            field.widget.can_delete_related = False
        return field

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'event':
            # allow to restrict event
            if request.GET.get('event_pk'):
                kwargs['queryset'] = models.Event.objects.filter(
                    pk=int(request.GET['event_pk']))
187
        elif db_field.name == 'member':
188
            kwargs['queryset'] = Member.active_members.all()
Thom Wiggers's avatar
Thom Wiggers committed
189
        return super().formfield_for_foreignkey(db_field, request, **kwargs)