Newer
Older
from django.apps import apps
Benjamin Hättasch
committed
from django.contrib.admin import SimpleListFilter, RelatedFieldListFilter
from django.db.models import Count, F
from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from rest_framework.reverse import reverse
from AKModel.availability.forms import AvailabilitiesFormMixin
from AKModel.availability.models import Availability
from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequirement, AK, AKSlot, Room, AKOrgaMessage, \
ConstraintViolation
from AKModel.urls import get_admin_urls_event_wizard, get_admin_urls_event
Benjamin Hättasch
committed
class EventRelatedFieldListFilter(RelatedFieldListFilter):
def field_choices(self, field, request, model_admin):
ordering = self.field_admin_ordering(field, request, model_admin)
limit_choices = {}
if "event__id__exact" in request.GET:
limit_choices['event__id__exact'] = request.GET["event__id__exact"]
return field.get_choices(include_blank=False, limit_choices_to=limit_choices, ordering=ordering)
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
list_display = ['name', 'status_url', 'place', 'start', 'end', 'active']
list_filter = ['active']
list_editable = ['active']
readonly_fields = ['status_url']
def add_view(self, request, form_url='', extra_context=None):
# Always use wizard to create new events (the built-in form wouldn't work anyways since the timezone cannot
# be specified before starting to fill the form)
return redirect("admin:new_event_wizard_start")
def get_urls(self):
urls = get_admin_urls_event_wizard(self.admin_site)
urls.extend(get_admin_urls_event(self.admin_site))
Benjamin Hättasch
committed
if apps.is_installed("AKScheduling"):
from AKScheduling.urls import get_admin_urls_scheduling
urls.extend(get_admin_urls_scheduling(self.admin_site))
urls.extend(super().get_urls())
return urls
def status_url(self, obj):
return format_html("<a href='{url}'>{text}</a>",
url=reverse_lazy('admin:event_status', kwargs={'slug': obj.slug}), text=_("Status"))
status_url.short_description = _("Status")
def get_form(self, request, obj=None, change=False, **kwargs):
# Use timezone of event
timezone.activate(obj.timezone)
return super().get_form(request, obj, change, **kwargs)
@admin.register(AKOwner)
class AKOwnerAdmin(admin.ModelAdmin):
model = AKOwner
list_display = ['name', 'institution', 'event']
Benjamin Hättasch
committed
list_filter = ['event', 'institution']
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKOwnerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(AKCategory)
class AKCategoryAdmin(admin.ModelAdmin):
model = AKCategory
list_display = ['name', 'color', 'event']
list_filter = ['event']
list_editable = ['color']
ordering = ['name']
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKCategoryAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(AKTrack)
class AKTrackAdmin(admin.ModelAdmin):
model = AKTrack
list_display = ['name', 'color', 'event']
list_filter = ['event']
list_editable = ['color']
ordering = ['name']
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKTrackAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(AKTag)
class AKTagAdmin(admin.ModelAdmin):
model = AKTag
list_display = ['name']
list_filter = []
list_editable = []
ordering = ['name']
@admin.register(AKRequirement)
class AKRequirementAdmin(admin.ModelAdmin):
model = AKRequirement
list_display = ['name', 'event']
list_filter = ['event']
list_editable = []
ordering = ['name']
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKRequirementAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
class WishFilter(SimpleListFilter):
title = _("Wish") # a label for our filter
parameter_name = 'wishes' # you can put anything here
def lookups(self, request, model_admin):
# This is where you create filter options; we have two:
return [
('WISH', _("Is wish")),
('NO_WISH', _("Is not a wish")),
]
def queryset(self, request, queryset):
annotated_queryset = queryset.annotate(owner_count=Count(F('owners')))
if self.value() == 'NO_WISH':
return annotated_queryset.filter(owner_count__gt=0)
if self.value() == 'WISH':
return annotated_queryset.filter(owner_count=0)
return queryset
Benjamin Hättasch
committed
class AKAdminForm(forms.ModelForm):
class Meta:
widgets = {
'requirements': forms.CheckboxSelectMultiple,
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Filter possible values for foreign keys & m2m when event is specified
if hasattr(self.instance, "event") and self.instance.event is not None:
self.fields["category"].queryset = AKCategory.objects.filter(event=self.instance.event)
self.fields["track"].queryset = AKTrack.objects.filter(event=self.instance.event)
self.fields["owners"].queryset = AKOwner.objects.filter(event=self.instance.event)
self.fields["requirements"].queryset = AKRequirement.objects.filter(event=self.instance.event)
self.fields["conflicts"].queryset = AK.objects.filter(event=self.instance.event)
self.fields["prerequisites"].queryset = AK.objects.filter(event=self.instance.event)
list_display = ['name', 'short_name', 'category', 'track', 'is_wish', 'interest', 'interest_counter', 'event']
Benjamin Hättasch
committed
list_filter = ['event', WishFilter, ('category', EventRelatedFieldListFilter), ('requirements', EventRelatedFieldListFilter)]
list_editable = ['short_name', 'track', 'interest_counter']
ordering = ['pk']
Benjamin Hättasch
committed
form = AKAdminForm
def wiki_export(self, request, queryset):
return render(request, 'admin/AKModel/wiki_export.html', context={"AKs": queryset})
wiki_export.short_description = _("Export to wiki syntax")
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
class RoomForm(AvailabilitiesFormMixin, forms.ModelForm):
class Meta:
model = Room
fields = ['name',
'location',
'capacity',
'properties',
'event',
]
widgets = {
'properties': forms.CheckboxSelectMultiple,
}
def __init__(self, *args, **kwargs):
# Init availability mixin
kwargs['initial'] = dict()
super().__init__(*args, **kwargs)
self.initial = {**self.initial, **kwargs['initial']}
Benjamin Hättasch
committed
# Filter possible values for m2m when event is specified
if hasattr(self.instance, "event") and self.instance.event is not None:
self.fields["properties"].queryset = AKRequirement.objects.filter(event=self.instance.event)
@admin.register(Room)
class RoomAdmin(admin.ModelAdmin):
model = Room
list_display = ['name', 'location', 'capacity', 'event']
Benjamin Hättasch
committed
list_filter = ['event', ('properties', EventRelatedFieldListFilter), 'location']
change_form_template = "admin/AKModel/room_change_form.html"
def get_form(self, request, obj=None, change=False, **kwargs):
if obj is not None:
return RoomForm
return super().get_form(request, obj, change, **kwargs)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(RoomAdmin, self).formfield_for_foreignkey(
db_field, request, **kwargs
)
Benjamin Hättasch
committed
class AKSlotAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Filter possible values for foreign keys when event is specified
if hasattr(self.instance, "event") and self.instance.event is not None:
self.fields["ak"].queryset = AK.objects.filter(event=self.instance.event)
self.fields["room"].queryset = Room.objects.filter(event=self.instance.event)
@admin.register(AKSlot)
class AKSlotAdmin(admin.ModelAdmin):
model = AKSlot
list_display = ['id', 'ak', 'room', 'start', 'duration', 'event']
Benjamin Hättasch
committed
list_filter = ['event', ('room', EventRelatedFieldListFilter)]
readonly_fields = ['ak_details_link', 'updated']
Benjamin Hättasch
committed
form = AKSlotAdminForm
def get_form(self, request, obj=None, change=False, **kwargs):
# Use timezone of associated event
if obj is not None and obj.event.timezone:
timezone.activate(obj.event.timezone)
# No timezone available? Use UTC
else:
timezone.activate("UTC")
return super().get_form(request, obj, change, **kwargs)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'event':
kwargs['initial'] = Event.get_next_active()
return super(AKSlotAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
def ak_details_link(self, akslot):
if apps.is_installed("AKSubmission") and akslot.ak is not None:
link = f"<a href={reverse('submit:ak_detail', args=[akslot.event.slug, akslot.ak.pk])}>{str(akslot.ak)}</a>"
return mark_safe(link)
return "-"
ak_details_link.short_description = _('AK Details')
@admin.register(Availability)
class AvailabilityAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, change=False, **kwargs):
# Use timezone of associated event
if obj is not None and obj.event.timezone:
timezone.activate(obj.event.timezone)
# No timezone available? Use UTC
else:
timezone.activate("UTC")
return super().get_form(request, obj, change, **kwargs)
@admin.register(AKOrgaMessage)
class AKOrgaMessageAdmin(admin.ModelAdmin):
list_display = ['timestamp', 'ak', 'text']
list_filter = ['ak__event']
readonly_fields = ['timestamp', 'ak', 'text']
Benjamin Hättasch
committed
class ConstraintViolationAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Filter possible values for foreign keys & m2m when event is specified
if hasattr(self.instance, "event") and self.instance.event is not None:
self.fields["ak_owner"].queryset = AKOwner.objects.filter(event=self.instance.event)
self.fields["room"].queryset = Room.objects.filter(event=self.instance.event)
self.fields["requirement"].queryset = AKRequirement.objects.filter(event=self.instance.event)
self.fields["category"].queryset = AKCategory.objects.filter(event=self.instance.event)
self.fields["aks"].queryset = AK.objects.filter(event=self.instance.event)
self.fields["ak_slots"].queryset = AKSlot.objects.filter(event=self.instance.event)
@admin.register(ConstraintViolation)
class ConstraintViolationAdmin(admin.ModelAdmin):
list_display = ['type', 'level', 'get_details']
list_filter = ['event']
readonly_fields = ['timestamp']
Benjamin Hättasch
committed
form = ConstraintViolationAdminForm