feat: bulk add courses to base catalog - #67
Conversation
|
@ccantillo in future please add screenshots! I have tested locally and it seems to be working fine. Nevertheless, this is not good enough! The functionality requested needs to be improved. We can't just "Add Bulk Courses" but also we need to improve it so it is a "Manage Bulk Courses". Screenshots of the corporate module:
Screenshot of Manage User Group:
On refresh it still loads the existing groups. |
Hi @igobranco, thanks for the feedback! Reworked the implementation to match the auth/group pattern. The "Bulk Add Courses" separate page is gone — the FilteredSelectMultiple widget now lives directly on the BaseCatalog change form, pre-populated with the catalog's current courses on load. A single Save now handles both additions and removals: it diffs the selected set against the current BaseCatalogCourse entries, creates the new ones (preserving added_by/added_at metadata), and deletes the removed ones.
|
ManuelStarDo
left a comment
There was a problem hiding this comment.
Review
-
No test coverage was added for
save_related's diff/sync logic (add + remove in one save) or for theBaseCatalogAdminForm.__init__pre-population behavior. Existing test suite (tests/test_catalog_course_service.py) only covers the unrelatedCatalogCourseService/PartnerCatalogadd/remove flow, not this newBaseCataloginline widget path. Given this directly manipulates DB state (create/delete) from rawcleaned_data, admin-level tests exercising add, remove, and no-op saves are warranted. -
The PR description/title still describe the old "Bulk Add Courses" separate-page approach (custom template,
get_urls(),bulk_add_courses_view()) — none of which exists in the final diff. This is a documentation mismatch that should be fixed before merging so reviewers and future readers aren't misled.
@ccantillo
Please address these 2 issues before merging
Hi @ManuelStarDo. Done. tests are in and the PR description is updated to match what was actually built. Let me know if anything else needs adjusting. |
ManuelStarDo
left a comment
There was a problem hiding this comment.
@ccantillo
I tested this locally and the feature is working.
Please just address these 2 changes and we can merge the PR.
Hi @ManuelStarDo. Both changes are done: Replaced except Exception with except FieldDoesNotExist — now catches only what's intended. |
b1775a9 to
b83ca8b
Compare
|
I did a rebase to fix the CI problems regarding the I don't know if I messed up the rebase, but the PR is now failing at a specific Python CI test. If not, then please fix the code/test so it passes CI Apart from that, i tested everything locally and it was working. With the CI/rebase issues addressed, we are good for merging |
|
Hi @ManuelStarDo Fixed and pushed. should be good now |








Manage courses inline on BaseCatalog change form
Summary
Administrators could only add one course at a time to the Base Catalog, which
was impractical when dealing with dozens or hundreds of courses. This PR embeds
a dual-panel course manager directly on the
BaseCatalogchange form, mirroringthe behaviour of Django's built-in
auth/groupadmin. Courses can be added andremoved in a single save operation, with the current state pre-loaded on every
page open.
What changed
partner_catalog/admin.pyBaseCatalogAdminForm— aModelFormwith a customcoursesfieldusing Django's
FilteredSelectMultiplewidget. On load,__init__setscourses.initialto the catalog's currently assigned courses so the rightpanel is pre-populated.
get_fields()toBaseCatalogAdmin— returns the field list atruntime (including
courses) to bypass Django's staticadmin.E013check,which forbids listing M2M-with-through-model fields in the class-level
fieldsattribute.save_related()toBaseCatalogAdmin— diffs the submitted selectionagainst current
BaseCatalogCourseentries and:BaseCatalogCourserows for newly selected courses(preserving
added_by/added_atmetadata).manage_coursescolumn to link to the catalog change page.tests/test_base_catalog_admin.py(new)Nine pytest tests covering:
BaseCatalogAdminForm.__init__— queryset population, empty initial for anew catalog, pre-populated initial for an existing catalog with courses.
BaseCatalogAdmin.save_related— add, remove, no-op,added_bytracking,and clear-all scenarios.
How the widget works
The
FilteredSelectMultiplewidget renders as a dual-panel picker directly onthe
BaseCatalogchange form. No separate page or URL is needed.Ctrl + click(orCmd + clickon Mac) each courseOn Save, all additions and removals are applied atomically.
Files changed
openedx-corporatepartner_catalog/admin.pyBaseCatalogAdminForm,get_fields,save_related, updated list columnopenedx-corporatetests/test_base_catalog_admin.pyTesting
/admin/partner_catalog/basecatalog/.the right panel.
Ctrl+click, and arrows.Total Courses count and the widget on the next load.
selection exactly.