Adam Goldsmith
2d16029ed7
All checks were successful
Ruff / ruff (push) Successful in 22s
to avoid issues with saving new objects with GeneratedFields when the pk is set
176 lines
4.9 KiB
Python
176 lines
4.9 KiB
Python
from django.contrib import admin
|
|
from django.contrib.humanize.templatetags.humanize import naturaltime
|
|
from django.utils.html import format_html
|
|
|
|
from django_object_actions import (
|
|
DjangoObjectActions,
|
|
action,
|
|
takes_instance_or_queryset,
|
|
)
|
|
from django_q.models import Task
|
|
from django_q.tasks import async_task
|
|
|
|
from .models import (
|
|
Event,
|
|
EventExt,
|
|
EventInstructor,
|
|
EventMeetingTime,
|
|
Flag,
|
|
Member,
|
|
Transaction,
|
|
)
|
|
from .tasks.scrape import (
|
|
scrape_event_details,
|
|
scrape_membershipworks,
|
|
)
|
|
|
|
|
|
class ReadOnlyAdmin(admin.ModelAdmin):
|
|
def has_add_permission(self, request, obj=None):
|
|
return False
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return False
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return False
|
|
|
|
|
|
class BaseMembershipWorksAdmin(DjangoObjectActions, ReadOnlyAdmin):
|
|
changelist_actions = ("refresh_membershipworks_data",)
|
|
|
|
# internal method from DjangoObjectActions
|
|
def _get_tool_dict(self, tool_name):
|
|
tool = super(DjangoObjectActions, self)._get_tool_dict(tool_name)
|
|
if tool_name == "refresh_membershipworks_data":
|
|
try:
|
|
last_run_time = naturaltime(
|
|
Task.objects.filter(group=scrape_membershipworks.q_task_group)
|
|
.values_list("started", flat=True)
|
|
.latest("started")
|
|
)
|
|
except Task.DoesNotExist:
|
|
last_run_time = "Never"
|
|
tool["label"] = f"Refresh Data [Last Run {last_run_time}]"
|
|
return tool
|
|
|
|
@action
|
|
def refresh_membershipworks_data(self, request, obj):
|
|
async_task(scrape_membershipworks, group=scrape_membershipworks.q_task_group)
|
|
self.message_user(
|
|
request,
|
|
"Queued refresh, please wait a few seconds/minutes then refresh the page",
|
|
)
|
|
|
|
|
|
class MemberFlagInline(admin.TabularInline):
|
|
model = Member.flags.through
|
|
|
|
|
|
@admin.register(Member)
|
|
class MemberAdmin(BaseMembershipWorksAdmin):
|
|
search_fields = ["^first_name", "^last_name", "^account_name"]
|
|
inlines = [MemberFlagInline]
|
|
|
|
|
|
@admin.register(Flag)
|
|
class FlagAdmin(BaseMembershipWorksAdmin):
|
|
inlines = [MemberFlagInline]
|
|
list_display = ["name", "type"]
|
|
list_filter = ["type"]
|
|
show_facets = admin.ShowFacets.ALWAYS
|
|
search_fields = ["name"]
|
|
|
|
|
|
@admin.register(Transaction)
|
|
class TransactionAdmin(BaseMembershipWorksAdmin):
|
|
list_display = ["timestamp", "member", "name", "type", "sum", "note"]
|
|
list_filter = ["type"]
|
|
show_facets = admin.ShowFacets.ALWAYS
|
|
search_fields = ["member", "name", "type", "note"]
|
|
date_hierarchy = "timestamp"
|
|
|
|
|
|
class EventMeetingTimeInline(admin.TabularInline):
|
|
model = EventMeetingTime
|
|
extra = 0
|
|
min_num = 1
|
|
|
|
readonly_fields = ["duration"]
|
|
|
|
# TODO: remove when switched to GeneratedField
|
|
@admin.display()
|
|
def duration(self, obj):
|
|
return obj.duration
|
|
|
|
|
|
@admin.register(EventInstructor)
|
|
class EventInstructorAdmin(admin.ModelAdmin):
|
|
autocomplete_fields = ["member"]
|
|
search_fields = ["name", "member__account_name"]
|
|
|
|
|
|
@admin.register(EventExt)
|
|
class EventAdmin(DjangoObjectActions, admin.ModelAdmin):
|
|
inlines = [EventMeetingTimeInline]
|
|
list_display = [
|
|
"title",
|
|
"start",
|
|
"duration",
|
|
"count",
|
|
"cap",
|
|
"category",
|
|
]
|
|
list_filter = [
|
|
"category",
|
|
"calendar",
|
|
"venue",
|
|
("materials_fee", admin.EmptyFieldListFilter),
|
|
]
|
|
show_facets = admin.ShowFacets.ALWAYS
|
|
search_fields = ["eid", "title", "url"]
|
|
date_hierarchy = "start"
|
|
exclude = ["url", "details"]
|
|
autocomplete_fields = ["instructor"]
|
|
change_actions = ["fetch_details"]
|
|
actions = ["fetch_details"]
|
|
|
|
@property
|
|
def readonly_fields(self):
|
|
fields = []
|
|
for field in Event._meta.get_fields():
|
|
if field.auto_created or field.many_to_many or not field.concrete:
|
|
continue
|
|
elif field.name == "url":
|
|
fields.append("_url")
|
|
else:
|
|
fields.append(field.name)
|
|
fields.insert(fields.index("end") + 1, "duration")
|
|
fields.append("_details_timestamp")
|
|
return fields
|
|
|
|
@admin.display(ordering="duration")
|
|
def duration(self, obj):
|
|
return obj.duration
|
|
|
|
@admin.display(description="URL")
|
|
def _url(self, obj):
|
|
return format_html(
|
|
'<a href="https://claremontmakerspace.org/events/#!event/{0}">{0}</a>',
|
|
obj.url,
|
|
)
|
|
|
|
@admin.display(description="Last details fetch")
|
|
def _details_timestamp(self, obj):
|
|
return naturaltime(obj.details_timestamp)
|
|
|
|
@takes_instance_or_queryset
|
|
def fetch_details(self, request, queryset):
|
|
scrape_event_details(queryset)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return False
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return False
|