Lightweight catalog implementation via extensions
This proposal is an early response to the proposed DEPR of course-discovery.
Specifically from this comment, the new catalog app:
new catalog app: should this proposal take off, I believe we should put the core primitives like programs or catalog and write the most basic implementation possible. Then leave every bit of product development to plugins. I don't think that requirements for courses or anything so specific should be implemented in core. Mostly a models and calls to extension points should live there.
Roughly, when looking at the bare minimum requirements, out team looked at our current projects and the existing implementations of the same or very similar features in:
enterprise-catalog/blob/master/enterprise_catalog/apps/catalog/models.py
academic-innovation/platform-plugin-course-series/blob/basic-series-support/course_series/models.py
With this in mind, we are proposing a bare implementation that includes only:
FlexibleCatalogModel
course_runs: as manyToMany to CourseOverview
query_string: a string to match course_runs dinamically
slug: url friendly
name: for humans
get_course_runs: the method that either does fetches the course_runs
directly or that uses the query string for the dynamic
asignment. Implemented through filters so that
search: a method that does flexible search. This would be implemented via
filters so that the default implementation can be swapped. I would
also vouch for shipping with a mysql only implementation and one with
meilisearch
model specific openedx-filters: before meaningful changes are made
model specific openedx-events: after the catalog changes in a meaningful way
API REST:
CRUD on the FlexibleCatalog
the API must allow to set the course_runs or the query
the API to list the catalogs should use get_course_runs so that filters are respected
Search API that uses the search method so that filters are respected
Python API
get_catalogs: a public api method that includes filters to do access control
get_course_runs: for a catalog without exposing the model (for stability for those that can manage to only use this)
exposing the search api
CRUD on the Catalog
Naturally including the accompanying:
- docs
- serializers
- forms
- admin pages
- QA suite
- …
Nice, @Felipe Montoya.
I think:
The
FlexibleCatalogModelshould also have a “type” field, so that you can have several different types of catalog (e.g. dynamic vs. static) each managed by different plugins. This also lets us have a clean way to provide a default implementation (e.g. when “type = default”, always just usecourse_runs, ignorequery_string) that can be used alongside custom catalog types.It may be better to remove
course_runsandquery_stringentirely and just let inherited/one-to-one models define those. For example, a common requirement would be to have a static list of course sets (“catalog courses” like “Math 100”, not course runs like “Math 100 2024-Winter”), and if we only provide a many-to-many link to CourseOverview, we can’t do that even with this supposedly “flexible” model. (Note that get_course_runs() would still return runs in this example, but the list is defined in terms of catalog courses / course sets, not runs. e.g. it might return only the most recent run or some other criteria.) I think we also want to avoid anyone using thecourse_runsandquery_stringfields other than for implementing a new catalog type, and removing them from the base model is a great way to enforce that.I think in 80% of use cases, we can improve performance by requiring that
get_course_runsreturn a QuerySet of CourseOverview, which can then be used in further queries. The downside is that if a search engine is used, a query like “SELECT c FROM course_overview WHERE c.id IN (1, 5, 7, …)” must be constructed, but I think that’s fine.What does the
searchmethod do? Keyword search? Would it also support filtering like filter by org, filter by tag, filter by year, or more?Have you thought about how this could look like with programs?