Skip to content

Commit adf05f3

Browse files
authored
change admin display and add export to csv action (#244)
* change admin display and add export to csv action * disable exporting on BingoGrid model
1 parent 13711fb commit adf05f3

File tree

3 files changed

+73
-4
lines changed

3 files changed

+73
-4
lines changed

server/api/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
from django.urls import path, include
2020
from django.conf import settings
2121
from django.conf.urls.static import static
22+
from bingo.actions import export2csv
2223

2324
# This will not show in production. We will need use nginx to serve the media files in production
2425
media = static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2526

27+
admin.site.add_action(export2csv, "csv_export_selected")
28+
2629
urlpatterns = [
2730
path("admin/", admin.site.urls),
2831
path("api/", include("bingo.urls")),

server/bingo/actions.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from django.http import HttpResponse
2+
from django.contrib.admin import action
3+
from .models import User, TileInteraction
4+
5+
6+
def get_friendly_value(instance, field_name, value):
7+
display_method = f'get_{field_name}_display'
8+
if hasattr(instance, display_method):
9+
return getattr(instance, display_method)()
10+
else:
11+
# If it's not a choice field, return the raw value
12+
return value
13+
14+
15+
@action(description="Export selected objects as CSV")
16+
def export2csv(modeladmin, request, queryset):
17+
import csv
18+
19+
response = HttpResponse(
20+
content_type="text/csv",
21+
headers={
22+
"Content-Disposition": f'attachment; filename="{modeladmin.model._meta.model_name}s.csv"'},
23+
)
24+
25+
writer = csv.writer(response)
26+
if modeladmin.model == User:
27+
exclude = ('password', 'is_superuser', 'is_active')
28+
elif modeladmin.model == TileInteraction:
29+
exclude = ('image_display',)
30+
else:
31+
exclude = tuple()
32+
33+
fields = modeladmin.fields if modeladmin.fields else [
34+
f.name for f in modeladmin.model._meta.fields()]
35+
fields = [f for f in fields if f not in exclude]
36+
writer.writerow(fields)
37+
if modeladmin.model == User:
38+
queryset = queryset.filter(is_superuser=False, is_active=True)
39+
raw_values = queryset.values_list(*fields)
40+
readable_rows = []
41+
for instance, values in zip(queryset, raw_values):
42+
readable_rows.append((get_friendly_value(instance, field_name, value)
43+
for field_name, value in zip(fields, values)))
44+
45+
writer.writerows(readable_rows)
46+
return response

server/bingo/admin.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66

77
@admin.register(User)
8-
class AuthorAdmin(admin.ModelAdmin):
8+
class UserAdmin(admin.ModelAdmin):
99
# custom order of fields
1010
fields = ("username", "first_name", "last_name", "bio", "total_points", "email", "birthdate",
1111
"visibility", "avatar", "gender_identity", "indigenous_identity", "last_login", "is_active", "is_superuser", "password")
1212

13+
list_display = ("username", "first_name", "last_name", "total_points", "email", "birthdate",
14+
"visibility", "avatar", "gender_identity", "indigenous_identity", "is_superuser", "is_active")
15+
1316
def save_model(self, request, obj, form, change):
1417
if obj.pk is not None: # Existing user
1518
original_obj = self.model.objects.get(pk=obj.pk)
@@ -32,14 +35,31 @@ class ChallengeAdmin(admin.ModelAdmin):
3235
'points', 'total_completions')
3336
readonly_fields = ('total_completions', 'id')
3437

38+
list_display = fields
39+
40+
41+
@admin.register(Friendship)
42+
class FriendshipAdmin(admin.ModelAdmin):
43+
list_display = ('requester', 'receiver', 'status')
44+
fields = list_display
3545

36-
admin.site.register(Friendship)
37-
admin.site.register(BingoGrid)
46+
47+
@admin.register(BingoGrid)
48+
class BingoGridAdmin(admin.ModelAdmin):
49+
# disable the export2csv action
50+
def get_actions(self, request):
51+
actions = super().get_actions(request)
52+
return {k: v for k, v in actions.items() if k != 'csv_export_selected'}
3853

3954

4055
@admin.register(TileInteraction)
4156
class TileInteractionAdmin(admin.ModelAdmin):
42-
readonly_fields = ('image_display',)
57+
fields = ('user', 'grid', 'position', 'description', 'image', 'completed',
58+
'consent', 'date_started', 'date_completed', 'image_display')
59+
readonly_fields = ('image_display', 'date_started')
60+
61+
list_display = ('user', 'grid', 'position', 'completed',
62+
'consent', 'date_started', 'date_completed')
4363

4464
def image_display(self, obj):
4565
return obj.get_image_html()

0 commit comments

Comments
 (0)