diff --git a/enterprise_catalog/apps/catalog/admin.py b/enterprise_catalog/apps/catalog/admin.py
index a7217f27..26312109 100644
--- a/enterprise_catalog/apps/catalog/admin.py
+++ b/enterprise_catalog/apps/catalog/admin.py
@@ -1,6 +1,7 @@
from django.contrib import admin
from django.urls import reverse
-from django.utils.html import format_html
+from django.utils.html import format_html, format_html_join
+from django.utils.safestring import mark_safe
from edx_rbac.admin import UserRoleAssignmentAdmin
from enterprise_catalog.apps.catalog.constants import (
@@ -15,9 +16,19 @@
ContentMetadata,
EnterpriseCatalog,
EnterpriseCatalogRoleAssignment,
+ RestrictedCourseMetadata,
)
+def _html_list_from_objects(objs, viewname, str_callback=None):
+ str_callback = str_callback or str
+ return format_html_join(
+ sep=mark_safe('
'),
+ format_string='{}',
+ args_generator=((reverse(viewname, args=[obj.pk]), str_callback(obj)) for obj in objs),
+ )
+
+
class UnchangeableMixin(admin.ModelAdmin):
"""
Mixin for disabling changing models through the admin
@@ -59,17 +70,77 @@ class ContentMetadataAdmin(UnchangeableMixin):
)
readonly_fields = (
'associated_content_metadata',
- 'catalog_queries',
- 'get_catalog',
+ 'get_catalog_queries',
+ 'get_catalogs',
'modified',
)
+ exclude = (
+ 'catalog_queries',
+ )
+
+ @admin.display(description='Catalog Queries')
+ def get_catalog_queries(self, obj):
+ catalog_queries = obj.catalog_queries.all()
+ return _html_list_from_objects(
+ objs=catalog_queries,
+ viewname="admin:catalog_catalogquery_change",
+ str_callback=lambda cq: cq.short_str_for_listings(),
+ )
@admin.display(description='Enterprise Catalogs')
- def get_catalog(self, obj):
+ def get_catalogs(self, obj):
catalogs = EnterpriseCatalog.objects.filter(
catalog_query_id__in=obj.catalog_queries.all().values_list('id')
)
- return f"{list(catalogs)}"
+ return _html_list_from_objects(catalogs, "admin:catalog_enterprisecatalog_change")
+
+
+@admin.register(RestrictedCourseMetadata)
+class RestrictedCourseMetadataAdmin(UnchangeableMixin):
+ """ Admin configuration for the custom RestrictedCourseMetadata model. """
+ list_display = (
+ 'content_key',
+ 'get_catalog_query_for_list',
+ 'get_unrestricted_parent',
+ )
+ search_fields = (
+ 'content_key',
+ 'catalog_query',
+ )
+ readonly_fields = (
+ 'get_catalog_query',
+ 'get_catalogs',
+ 'modified',
+ )
+ exclude = (
+ 'catalog_query',
+ )
+
+ @admin.display(
+ description='Catalog Query'
+ )
+ def get_catalog_query_for_list(self, obj):
+ link = reverse("admin:catalog_catalogquery_change", args=[obj.catalog_query.id])
+ return format_html('{}', link, obj.catalog_query.short_str_for_listings())
+
+ @admin.display(
+ description='Catalog Query'
+ )
+ def get_catalog_query(self, obj):
+ link = reverse("admin:catalog_catalogquery_change", args=[obj.catalog_query.id])
+ return format_html('{}', link, obj.catalog_query.pretty_print_content_filter())
+
+ @admin.display(
+ description='Unrestricted Parent'
+ )
+ def get_unrestricted_parent(self, obj):
+ link = reverse("admin:catalog_contentmetadata_change", args=[obj.unrestricted_parent.id])
+ return format_html('{}', link, str(obj.unrestricted_parent))
+
+ @admin.display(description='Enterprise Catalogs')
+ def get_catalogs(self, obj):
+ catalogs = EnterpriseCatalog.objects.filter(catalog_query=obj.catalog_query)
+ return _html_list_from_objects(catalogs, "admin:catalog_enterprisecatalog_change")
@admin.register(CatalogQuery)
diff --git a/enterprise_catalog/apps/catalog/models.py b/enterprise_catalog/apps/catalog/models.py
index 8d561bf5..82b72913 100644
--- a/enterprise_catalog/apps/catalog/models.py
+++ b/enterprise_catalog/apps/catalog/models.py
@@ -166,6 +166,14 @@ def __str__(self):
f"and content_filter '{self.pretty_print_content_filter()}'>"
)
+ def short_str_for_listings(self):
+ """
+ Return *short* human-readable string representation for listings.
+ """
+ return (
+ f""
+ )
+
class EnterpriseCatalog(TimeStampedModel):
"""
@@ -715,11 +723,7 @@ def __str__(self):
"""
Return human-readable string representation.
"""
- return (
- "".format(
- content_key=self.content_key
- )
- )
+ return f"<{self.__class__.__name__} for '{self.content_key}'>"
class ContentMetadata(BaseContentMetadata):