Skip to content

Commit cf6487c

Browse files
authored
Merge pull request #1347 from makeabilitylab/1346-admin-changelist-quickwins
Admin changelist quick-wins + News thumbnail crash fix (#1346, Phase 1)
2 parents 324b3b7 + 66f31d5 commit cf6487c

15 files changed

Lines changed: 170 additions & 14 deletions

website/admin/artifact_admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ class ArtifactAdmin(admin.ModelAdmin):
1515

1616
# search_fields are used for auto-complete, see:
1717
# https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
18-
search_fields = ['title', 'forum_name']
18+
# Includes author first/last name so artifacts are findable by who wrote them
19+
# (Django auto-applies DISTINCT for the M2M join). Subclasses may extend this.
20+
search_fields = ['title', 'forum_name', 'authors__first_name', 'authors__last_name']
1921

2022
fieldsets = [
2123
(None, {'fields': ['title', 'authors', 'date']}),

website/admin/award_admin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class AwardAdmin(admin.ModelAdmin):
4444

4545
ordering = ('-date',)
4646

47+
date_hierarchy = 'date' # Year/month/day drill-down (awards are browsed by year)
48+
4749
def get_fieldsets(self, request, obj=None):
4850
# Built at request time so reverse() can resolve the Publications admin URL.
4951
publications_url = reverse('admin:website_publication_changelist')

website/admin/grant_admin.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ class GrantAdmin(ArtifactAdmin):
99

1010
# search_fields are used for auto-complete, see:
1111
# https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
12-
search_fields = ['title', 'date', 'forum_name']
12+
# Dropped 'date' (string-searching a DateField is unhelpful); added PI/Co-PI
13+
# (author) and sponsor name so grants are findable by people and funder.
14+
search_fields = ['title', 'forum_name', 'authors__first_name',
15+
'authors__last_name', 'sponsor__name']
1316

1417
# The list display lets us control what is shown in the default talk table at Home > Website > Grants
1518
# See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
@@ -21,6 +24,7 @@ class GrantAdmin(ArtifactAdmin):
2124
autocomplete_fields = ['sponsor']
2225

2326
ordering = ('-date',) # sort by date, most recent first
27+
date_hierarchy = 'date' # Year/month/day drill-down by grant start date
2428

2529
fieldsets = [
2630
(None, {'fields': ['title', 'authors']}),

website/admin/keyword_admin.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
class KeywordAdmin(admin.ModelAdmin):
88
list_display = ['keyword', 'project_count', 'publication_count']
99

10+
# The keyword table had no search box; alphabetical ordering also groups
11+
# near-duplicate tags (e.g. "Speech" / "speech") adjacently for cleanup.
12+
search_fields = ['keyword']
13+
ordering = ['keyword']
14+
1015
def change_view(self, request, object_id, form_url='', extra_context=None):
1116
"""Add projects and publications to the context. We then use this extra data in
1217
the change_form.html template to display the projects and publications that use this keyword.

website/admin/news_admin.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
from django.utils.html import format_html # for formatting thumbnails
1313
from easy_thumbnails.files import get_thumbnailer # for generating thumbnails
1414
import os # for checking if thumbnail file exists
15+
import logging
1516
from website.admin.admin_site import ml_admin_site
1617

18+
_logger = logging.getLogger(__name__)
19+
1720
class YearListFilter(admin.SimpleListFilter):
1821
title = 'year' # a label for our filter
1922
parameter_name = 'year' # you can put anything here
@@ -46,6 +49,12 @@ class Media:
4649
# Add a filter to the right sidebar that allows us to filter by year
4750
list_filter = (YearListFilter, 'project')
4851

52+
# Search by headline or author name (News previously had no search box).
53+
search_fields = ['title', 'author__first_name', 'author__last_name']
54+
55+
# Year/month/day drill-down at the top of the changelist (News is date-driven).
56+
date_hierarchy = 'date'
57+
4958
# Define 'author' as an auto-complete field. We must then also define "search_fields"
5059
# in PersonAdmin or we'll receive a Django error
5160
autocomplete_fields = ['author']
@@ -55,12 +64,18 @@ class Media:
5564

5665
def get_display_thumbnail(self, obj):
5766
if obj.image and os.path.isfile(obj.image.path):
58-
# Use easy_thumbnails to generate a thumbnail
59-
thumbnailer = get_thumbnailer(obj.image)
60-
thumbnail_options = {'size': (NEWS_THUMBNAIL_SIZE[0], NEWS_THUMBNAIL_SIZE[1]), 'crop': True}
61-
thumbnail_url = thumbnailer.get_thumbnail(thumbnail_options).url
62-
63-
return format_html('<img src="{}" height="50" style="border-radius: 5%;"/>', thumbnail_url)
67+
try:
68+
# Use easy_thumbnails to generate a thumbnail
69+
thumbnailer = get_thumbnailer(obj.image)
70+
thumbnail_options = {'size': (NEWS_THUMBNAIL_SIZE[0], NEWS_THUMBNAIL_SIZE[1]), 'crop': True}
71+
thumbnail_url = thumbnailer.get_thumbnail(thumbnail_options).url
72+
73+
return format_html('<img src="{}" height="50" style="border-radius: 5%;"/>', thumbnail_url)
74+
except Exception:
75+
# A single corrupt/unreadable image must not 500 the entire News
76+
# changelist (the column is rendered for every row).
77+
_logger.warning("Could not generate admin thumbnail for News id=%s", obj.pk, exc_info=True)
78+
return 'No Thumbnail'
6479
return 'No Thumbnail'
6580

6681
get_display_thumbnail.short_description = 'Thumbnail'

website/admin/photo_admin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
class PhotoAdmin(ImageCroppingMixin, admin.ModelAdmin):
88
list_display = ('admin_thumbnail', 'caption', 'alt_text', 'get_resolution_as_str',
99
'cropping', 'picture')
10-
10+
11+
# Photos had no search box; search caption/alt text and the owning project.
12+
search_fields = ['caption', 'alt_text', 'project__name']
13+
1114
list_per_page = 20 # changes how many images to show on a single admin page

website/admin/position_admin.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
class PositionAdmin(admin.ModelAdmin):
99
"""Note: We do not want users to edit positions directly. Instead, we want them to edit people and projects.
1010
See PositionInline in PersonAdmin"""
11+
# Needed for autocomplete/search to filter rather than return everything;
12+
# the get_search_results override below builds on this base.
13+
search_fields = ['person__first_name', 'person__last_name', 'title']
14+
1115
def get_model_perms(self, request):
1216
"""
1317
Return empty perms dict thus hiding the model from admin index.

website/admin/poster_admin.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ class PosterAdmin(ArtifactAdmin):
1313

1414
# search_fields are used for auto-complete, see:
1515
# https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
16-
search_fields = ['title', 'date']
16+
# Was ['title', 'date'] — string-searching a DateField is unhelpful; search
17+
# venue and author instead (matches the other artifact admins).
18+
search_fields = ['title', 'forum_name', 'authors__first_name', 'authors__last_name']
19+
20+
ordering = ('-date',) # Poster had no default sort; newest first like its siblings
21+
date_hierarchy = 'date' # Year/month/day drill-down
1722

1823
def get_changeform_initial_data(self, request):
1924
"""

website/admin/project_admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ class GrantInline(admin.TabularInline):
4848

4949
@admin.register(Project, site=ml_admin_site)
5050
class ProjectAdmin(ImageCroppingMixin, admin.ModelAdmin):
51-
search_fields = ['name'] # allows you to search by the name of the project
51+
# Search by name plus the research-area facets editors think in (umbrella, keyword).
52+
search_fields = ['name', 'short_name', 'project_umbrellas__name', 'keywords__name']
53+
ordering = ('name',) # deterministic alphabetical sort (matched the autocomplete already)
5254
inlines = [GrantInline, BannerInline, PhotoInline, ProjectRoleInline]
5355

5456
# The list display lets us control what is shown in the Project table at Home > Website > Project

website/admin/project_umbrella_admin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class ProjectInline(admin.TabularInline): # or admin.StackedInline
1111
@admin.register(ProjectUmbrella, site=ml_admin_site)
1212
class ProjectUmbrellaAdmin(admin.ModelAdmin):
1313
list_display = ('name', 'short_name', 'project_count')
14+
search_fields = ['name', 'short_name']
15+
ordering = ('name',)
1416
inlines = [ProjectInline]
1517

1618
def formfield_for_manytomany(self, db_field, request=None, **kwargs):

0 commit comments

Comments
 (0)