openedx-learning 0.19.2__tar.gz → 0.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openedx_learning-0.19.2/openedx_learning.egg-info → openedx_learning-0.22.0}/PKG-INFO +5 -4
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/__init__.py +1 -1
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/api.py +46 -1
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/api.py +1 -55
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/api.py +84 -52
- openedx_learning-0.22.0/openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py +17 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/api.py +23 -24
- {openedx_learning-0.19.2 → openedx_learning-0.22.0/openedx_learning.egg-info}/PKG-INFO +5 -4
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/SOURCES.txt +1 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/requires.txt +3 -3
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/requirements/base.in +1 -1
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/setup.py +1 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/CHANGELOG.rst +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/LICENSE.txt +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/MANIFEST.in +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/README.rst +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/api/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/api/authoring.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/api/authoring_models.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/admin.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/collections/models.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/admin.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/management/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/management/commands/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/management/commands/add_assets_to_component.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/components/models.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/admin.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/api.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/models.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/admin.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/migrations/0003_containers.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/container.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/draft_published.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/entity_list.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/learning_package.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/publish_log.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/publishing/models/publishable_entity.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/models.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/urls.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/views.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/admin_utils.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/cache.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/collations.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/fields.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/managers.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/test_utils.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/lib/validators.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/py.typed +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/dependency_links.txt +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/not-zip-safe +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/top_level.txt +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/admin.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/api.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/apps.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/data.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/actions.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/api.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/exceptions.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/import_plan.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/parsers.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/tasks.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/template.csv +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/import_export/template.json +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0001_initial.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0001_squashed.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0002_auto_20230718_2026.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0003_auto_20230721_1238.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0004_auto_20230723_2001.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0005_language_taxonomy.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0006_alter_objecttag_unique_together.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0006_auto_20230802_1631.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0007_tag_import_task_log_null_fix.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0008_taxonomy_description_not_null.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0010_cleanups.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0011_remove_required.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0012_language_taxonomy.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0013_tag_parent_blank.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0014_minor_fixes.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0015_taxonomy_export_id.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0016_object_tag_export_id.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0017_alter_tagimporttask_status.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/0018_objecttag_is_copied.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/migrations/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/base.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/import_export.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/system_defined.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/utils.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/paginators.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/urls.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/utils.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/__init__.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/permissions.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/serializers.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/urls.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/views.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/views_import.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rules.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/urls.py +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/py.typed +0 -0
- {openedx_learning-0.19.2 → openedx_learning-0.22.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openedx-learning
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: Open edX Learning Core and Tagging.
|
|
5
5
|
Home-page: https://github.com/openedx/openedx-learning
|
|
6
6
|
Author: David Ormsbee
|
|
@@ -10,6 +10,7 @@ Keywords: Python edx
|
|
|
10
10
|
Classifier: Development Status :: 3 - Alpha
|
|
11
11
|
Classifier: Framework :: Django
|
|
12
12
|
Classifier: Framework :: Django :: 4.2
|
|
13
|
+
Classifier: Framework :: Django :: 5.2
|
|
13
14
|
Classifier: Intended Audience :: Developers
|
|
14
15
|
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
15
16
|
Classifier: Natural Language :: English
|
|
@@ -18,12 +19,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
20
|
Requires-Python: >=3.11
|
|
20
21
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist:
|
|
22
|
+
Requires-Dist: attrs
|
|
22
23
|
Requires-Dist: rules<4.0
|
|
23
24
|
Requires-Dist: djangorestframework<4.0
|
|
24
|
-
Requires-Dist: Django<5.0
|
|
25
25
|
Requires-Dist: celery
|
|
26
|
-
Requires-Dist:
|
|
26
|
+
Requires-Dist: Django
|
|
27
|
+
Requires-Dist: edx-drf-extensions
|
|
27
28
|
Dynamic: author
|
|
28
29
|
Dynamic: author-email
|
|
29
30
|
Dynamic: classifier
|
|
@@ -10,7 +10,7 @@ from django.db.models import QuerySet
|
|
|
10
10
|
|
|
11
11
|
from ..publishing import api as publishing_api
|
|
12
12
|
from ..publishing.models import PublishableEntity
|
|
13
|
-
from .models import Collection
|
|
13
|
+
from .models import Collection, CollectionPublishableEntity
|
|
14
14
|
|
|
15
15
|
# The public API that will be re-exported by openedx_learning.apps.authoring.api
|
|
16
16
|
# is listed in the __all__ entries below. Internal helper functions that are
|
|
@@ -27,6 +27,7 @@ __all__ = [
|
|
|
27
27
|
"remove_from_collection",
|
|
28
28
|
"restore_collection",
|
|
29
29
|
"update_collection",
|
|
30
|
+
"set_collections",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
|
|
@@ -204,3 +205,47 @@ def get_collections(learning_package_id: int, enabled: bool | None = True) -> Qu
|
|
|
204
205
|
if enabled is not None:
|
|
205
206
|
qs = qs.filter(enabled=enabled)
|
|
206
207
|
return qs.select_related("learning_package").order_by('pk')
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def set_collections(
|
|
211
|
+
publishable_entity: PublishableEntity,
|
|
212
|
+
collection_qset: QuerySet[Collection],
|
|
213
|
+
created_by: int | None = None,
|
|
214
|
+
) -> set[Collection]:
|
|
215
|
+
"""
|
|
216
|
+
Set collections for a given publishable entity.
|
|
217
|
+
|
|
218
|
+
These Collections must belong to the same LearningPackage as the PublishableEntity,
|
|
219
|
+
or a ValidationError will be raised.
|
|
220
|
+
|
|
221
|
+
Modified date of all collections related to entity is updated.
|
|
222
|
+
|
|
223
|
+
Returns the updated collections.
|
|
224
|
+
"""
|
|
225
|
+
# Disallow adding entities outside the collection's learning package
|
|
226
|
+
if collection_qset.exclude(learning_package_id=publishable_entity.learning_package_id).count():
|
|
227
|
+
raise ValidationError(
|
|
228
|
+
"Collection entities must be from the same learning package as the collection.",
|
|
229
|
+
)
|
|
230
|
+
current_relations = CollectionPublishableEntity.objects.filter(
|
|
231
|
+
entity=publishable_entity
|
|
232
|
+
).select_related('collection')
|
|
233
|
+
# Clear other collections for given entity and add only new collections from collection_qset
|
|
234
|
+
removed_collections = set(
|
|
235
|
+
r.collection for r in current_relations.exclude(collection__in=collection_qset)
|
|
236
|
+
)
|
|
237
|
+
new_collections = set(collection_qset.exclude(
|
|
238
|
+
id__in=current_relations.values_list('collection', flat=True)
|
|
239
|
+
))
|
|
240
|
+
# Triggers a m2m_changed signal
|
|
241
|
+
publishable_entity.collections.set(
|
|
242
|
+
objs=collection_qset,
|
|
243
|
+
through_defaults={"created_by_id": created_by},
|
|
244
|
+
)
|
|
245
|
+
# Update modified date via update to avoid triggering post_save signal for all collections, which can be very slow.
|
|
246
|
+
affected_collection = removed_collections | new_collections
|
|
247
|
+
Collection.objects.filter(
|
|
248
|
+
id__in=[collection.id for collection in affected_collection]
|
|
249
|
+
).update(modified=datetime.now(tz=timezone.utc))
|
|
250
|
+
|
|
251
|
+
return affected_collection
|
|
@@ -13,18 +13,16 @@ are stored in this app.
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
15
|
import mimetypes
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime
|
|
17
17
|
from enum import StrEnum, auto
|
|
18
18
|
from logging import getLogger
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from uuid import UUID
|
|
21
21
|
|
|
22
|
-
from django.core.exceptions import ValidationError
|
|
23
22
|
from django.db.models import Q, QuerySet
|
|
24
23
|
from django.db.transaction import atomic
|
|
25
24
|
from django.http.response import HttpResponse, HttpResponseNotFound
|
|
26
25
|
|
|
27
|
-
from ..collections.models import Collection, CollectionPublishableEntity
|
|
28
26
|
from ..contents import api as contents_api
|
|
29
27
|
from ..publishing import api as publishing_api
|
|
30
28
|
from .models import Component, ComponentType, ComponentVersion, ComponentVersionContent
|
|
@@ -51,7 +49,6 @@ __all__ = [
|
|
|
51
49
|
"look_up_component_version_content",
|
|
52
50
|
"AssetError",
|
|
53
51
|
"get_redirect_response_for_component_asset",
|
|
54
|
-
"set_collections",
|
|
55
52
|
]
|
|
56
53
|
|
|
57
54
|
|
|
@@ -605,54 +602,3 @@ def get_redirect_response_for_component_asset(
|
|
|
605
602
|
)
|
|
606
603
|
|
|
607
604
|
return HttpResponse(headers={**info_headers, **redirect_headers})
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
def set_collections(
|
|
611
|
-
learning_package_id: int,
|
|
612
|
-
component: Component,
|
|
613
|
-
collection_qset: QuerySet[Collection],
|
|
614
|
-
created_by: int | None = None,
|
|
615
|
-
) -> set[Collection]:
|
|
616
|
-
"""
|
|
617
|
-
Set collections for a given component.
|
|
618
|
-
|
|
619
|
-
These Collections must belong to the same LearningPackage as the Component, or a ValidationError will be raised.
|
|
620
|
-
|
|
621
|
-
Modified date of all collections related to component is updated.
|
|
622
|
-
|
|
623
|
-
Returns the updated collections.
|
|
624
|
-
"""
|
|
625
|
-
# Disallow adding entities outside the collection's learning package
|
|
626
|
-
invalid_collection = collection_qset.exclude(learning_package_id=learning_package_id).first()
|
|
627
|
-
if invalid_collection:
|
|
628
|
-
raise ValidationError(
|
|
629
|
-
f"Cannot add collection {invalid_collection.pk} in learning package "
|
|
630
|
-
f"{invalid_collection.learning_package_id} to component {component} in "
|
|
631
|
-
f"learning package {learning_package_id}."
|
|
632
|
-
)
|
|
633
|
-
current_relations = CollectionPublishableEntity.objects.filter(
|
|
634
|
-
entity=component.publishable_entity
|
|
635
|
-
).select_related('collection')
|
|
636
|
-
# Clear other collections for given component and add only new collections from collection_qset
|
|
637
|
-
removed_collections = set(
|
|
638
|
-
r.collection for r in current_relations.exclude(collection__in=collection_qset)
|
|
639
|
-
)
|
|
640
|
-
new_collections = set(collection_qset.exclude(
|
|
641
|
-
id__in=current_relations.values_list('collection', flat=True)
|
|
642
|
-
))
|
|
643
|
-
# Use `remove` instead of `CollectionPublishableEntity.delete()` to trigger m2m_changed signal which will handle
|
|
644
|
-
# updating component index.
|
|
645
|
-
component.publishable_entity.collections.remove(*removed_collections)
|
|
646
|
-
component.publishable_entity.collections.add(
|
|
647
|
-
*new_collections,
|
|
648
|
-
through_defaults={"created_by_id": created_by},
|
|
649
|
-
)
|
|
650
|
-
# Update modified date via update to avoid triggering post_save signal for collections
|
|
651
|
-
# The signal triggers index update for each collection synchronously which will be very slow in this case.
|
|
652
|
-
# Instead trigger the index update in the caller function asynchronously.
|
|
653
|
-
affected_collection = removed_collections | new_collections
|
|
654
|
-
Collection.objects.filter(
|
|
655
|
-
id__in=[collection.id for collection in affected_collection]
|
|
656
|
-
).update(modified=datetime.now(tz=timezone.utc))
|
|
657
|
-
|
|
658
|
-
return affected_collection
|
|
@@ -74,8 +74,10 @@ __all__ = [
|
|
|
74
74
|
"get_container",
|
|
75
75
|
"get_container_by_key",
|
|
76
76
|
"get_containers",
|
|
77
|
+
"get_collection_containers",
|
|
77
78
|
"ChildrenEntitiesAction",
|
|
78
79
|
"ContainerEntityListEntry",
|
|
80
|
+
"ContainerEntityRow",
|
|
79
81
|
"get_entities_in_container",
|
|
80
82
|
"contains_unpublished_changes",
|
|
81
83
|
"get_containers_with_entity",
|
|
@@ -639,8 +641,7 @@ def create_entity_list() -> EntityList:
|
|
|
639
641
|
|
|
640
642
|
|
|
641
643
|
def create_entity_list_with_rows(
|
|
642
|
-
|
|
643
|
-
entity_version_pks: list[int | None],
|
|
644
|
+
entity_rows: list[ContainerEntityRow],
|
|
644
645
|
*,
|
|
645
646
|
learning_package_id: int | None,
|
|
646
647
|
) -> EntityList:
|
|
@@ -649,10 +650,7 @@ def create_entity_list_with_rows(
|
|
|
649
650
|
Create new entity list rows for an entity list.
|
|
650
651
|
|
|
651
652
|
Args:
|
|
652
|
-
|
|
653
|
-
entity_version_pks: The IDs of the versions of the entities
|
|
654
|
-
(PublishableEntityVersion) that the entity list rows reference, or
|
|
655
|
-
Nones for "unpinned" (default).
|
|
653
|
+
entity_rows: List of ContainerEntityRows specifying the publishable entity ID and version ID (if pinned).
|
|
656
654
|
learning_package_id: Optional. Verify that all the entities are from
|
|
657
655
|
the specified learning package.
|
|
658
656
|
|
|
@@ -662,13 +660,25 @@ def create_entity_list_with_rows(
|
|
|
662
660
|
# Do a quick check that the given entities are in the right learning package:
|
|
663
661
|
if learning_package_id:
|
|
664
662
|
if PublishableEntity.objects.filter(
|
|
665
|
-
pk__in=
|
|
663
|
+
pk__in=[entity.entity_pk for entity in entity_rows],
|
|
666
664
|
).exclude(
|
|
667
665
|
learning_package_id=learning_package_id,
|
|
668
666
|
).exists():
|
|
669
667
|
raise ValidationError("Container entities must be from the same learning package.")
|
|
670
668
|
|
|
671
|
-
|
|
669
|
+
# Ensure that any pinned entity versions are linked to the correct entity
|
|
670
|
+
pinned_entities = {
|
|
671
|
+
entity.version_pk: entity.entity_pk
|
|
672
|
+
for entity in entity_rows if entity.pinned
|
|
673
|
+
}
|
|
674
|
+
if pinned_entities:
|
|
675
|
+
entity_versions = PublishableEntityVersion.objects.filter(
|
|
676
|
+
pk__in=pinned_entities.keys(),
|
|
677
|
+
).only('pk', 'entity_id')
|
|
678
|
+
for entity_version in entity_versions:
|
|
679
|
+
if pinned_entities[entity_version.pk] != entity_version.entity_id:
|
|
680
|
+
raise ValidationError("Container entity versions must belong to the specified entity.")
|
|
681
|
+
|
|
672
682
|
with atomic(savepoint=False):
|
|
673
683
|
|
|
674
684
|
entity_list = create_entity_list()
|
|
@@ -676,13 +686,11 @@ def create_entity_list_with_rows(
|
|
|
676
686
|
[
|
|
677
687
|
EntityListRow(
|
|
678
688
|
entity_list=entity_list,
|
|
679
|
-
entity_id=entity_pk,
|
|
689
|
+
entity_id=entity.entity_pk,
|
|
680
690
|
order_num=order_num,
|
|
681
|
-
entity_version_id=
|
|
682
|
-
)
|
|
683
|
-
for order_num, entity_pk, entity_version_pk in zip(
|
|
684
|
-
order_nums, entity_pks, entity_version_pks
|
|
691
|
+
entity_version_id=entity.version_pk,
|
|
685
692
|
)
|
|
693
|
+
for order_num, entity in enumerate(entity_rows)
|
|
686
694
|
]
|
|
687
695
|
)
|
|
688
696
|
return entity_list
|
|
@@ -725,8 +733,7 @@ def create_container_version(
|
|
|
725
733
|
version_num: int,
|
|
726
734
|
*,
|
|
727
735
|
title: str,
|
|
728
|
-
|
|
729
|
-
entity_version_pks: list[int | None] | None,
|
|
736
|
+
entity_rows: list[ContainerEntityRow],
|
|
730
737
|
created: datetime,
|
|
731
738
|
created_by: int | None,
|
|
732
739
|
container_version_cls: type[ContainerVersionModel] = ContainerVersion, # type: ignore[assignment]
|
|
@@ -739,8 +746,7 @@ def create_container_version(
|
|
|
739
746
|
container_id: The ID of the container that the version belongs to.
|
|
740
747
|
version_num: The version number of the container.
|
|
741
748
|
title: The title of the container.
|
|
742
|
-
|
|
743
|
-
entity_version_pks: The IDs of the versions to pin to, if pinning is desired.
|
|
749
|
+
entity_rows: List of ContainerEntityRows specifying the publishable entity ID and version ID (if pinned).
|
|
744
750
|
created: The date and time the container version was created.
|
|
745
751
|
created_by: The ID of the user who created the container version.
|
|
746
752
|
container_version_cls: The subclass of ContainerVersion to use, if applicable.
|
|
@@ -749,16 +755,13 @@ def create_container_version(
|
|
|
749
755
|
The newly created container version.
|
|
750
756
|
"""
|
|
751
757
|
assert title is not None
|
|
752
|
-
assert
|
|
758
|
+
assert entity_rows is not None
|
|
753
759
|
|
|
754
760
|
with atomic(savepoint=False):
|
|
755
761
|
container = Container.objects.select_related("publishable_entity").get(pk=container_id)
|
|
756
762
|
entity = container.publishable_entity
|
|
757
|
-
if entity_version_pks is None:
|
|
758
|
-
entity_version_pks = [None] * len(publishable_entities_pks)
|
|
759
763
|
entity_list = create_entity_list_with_rows(
|
|
760
|
-
|
|
761
|
-
entity_version_pks=entity_version_pks,
|
|
764
|
+
entity_rows=entity_rows,
|
|
762
765
|
learning_package_id=entity.learning_package_id,
|
|
763
766
|
)
|
|
764
767
|
container_version = _create_container_version(
|
|
@@ -785,8 +788,7 @@ class ChildrenEntitiesAction(Enum):
|
|
|
785
788
|
def create_next_entity_list(
|
|
786
789
|
learning_package_id: int,
|
|
787
790
|
last_version: ContainerVersion,
|
|
788
|
-
|
|
789
|
-
entity_version_pks: list[int | None] | None,
|
|
791
|
+
entity_rows: list[ContainerEntityRow],
|
|
790
792
|
entities_action: ChildrenEntitiesAction = ChildrenEntitiesAction.REPLACE,
|
|
791
793
|
) -> EntityList:
|
|
792
794
|
"""
|
|
@@ -795,55 +797,53 @@ def create_next_entity_list(
|
|
|
795
797
|
Args:
|
|
796
798
|
learning_package_id: Learning package ID
|
|
797
799
|
last_version: Last version of container.
|
|
798
|
-
|
|
799
|
-
entity_version_pks: The IDs of the versions to pin to, if pinning is desired.
|
|
800
|
+
entity_rows: List of ContainerEntityRows specifying the publishable entity ID and version ID (if pinned).
|
|
800
801
|
entities_action: APPEND, REMOVE or REPLACE given entities from/to the container
|
|
801
802
|
|
|
802
803
|
Returns:
|
|
803
804
|
The newly created entity list.
|
|
804
805
|
"""
|
|
805
|
-
if entity_version_pks is None:
|
|
806
|
-
entity_version_pks: list[int | None] = [None] * len(publishable_entities_pks) # type: ignore[no-redef]
|
|
807
806
|
if entities_action == ChildrenEntitiesAction.APPEND:
|
|
808
807
|
# get previous entity list rows
|
|
809
808
|
last_entities = last_version.entity_list.entitylistrow_set.only(
|
|
810
809
|
"entity_id",
|
|
811
810
|
"entity_version_id"
|
|
812
811
|
).order_by("order_num")
|
|
813
|
-
# append given
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
812
|
+
# append given entity_rows to the existing children
|
|
813
|
+
entity_rows = [
|
|
814
|
+
ContainerEntityRow(
|
|
815
|
+
entity_pk=entity.entity_id,
|
|
816
|
+
version_pk=entity.entity_version_id,
|
|
817
|
+
)
|
|
817
818
|
for entity in last_entities
|
|
818
|
-
] +
|
|
819
|
+
] + entity_rows
|
|
819
820
|
elif entities_action == ChildrenEntitiesAction.REMOVE:
|
|
820
|
-
# get previous entity list
|
|
821
|
+
# get previous entity list, excluding the entities in entity_rows
|
|
821
822
|
last_entities = last_version.entity_list.entitylistrow_set.only(
|
|
822
823
|
"entity_id",
|
|
823
824
|
"entity_version_id"
|
|
825
|
+
).exclude(
|
|
826
|
+
entity_id__in=[entity.entity_pk for entity in entity_rows]
|
|
824
827
|
).order_by("order_num")
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
828
|
+
entity_rows = [
|
|
829
|
+
ContainerEntityRow(
|
|
830
|
+
entity_pk=entity.entity_id,
|
|
831
|
+
version_pk=entity.entity_version_id,
|
|
832
|
+
)
|
|
833
|
+
for entity in last_entities.all()
|
|
830
834
|
]
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
entity_pks=publishable_entities_pks,
|
|
835
|
-
entity_version_pks=entity_version_pks, # type: ignore[arg-type]
|
|
835
|
+
|
|
836
|
+
return create_entity_list_with_rows(
|
|
837
|
+
entity_rows=entity_rows,
|
|
836
838
|
learning_package_id=learning_package_id,
|
|
837
839
|
)
|
|
838
|
-
return next_entity_list
|
|
839
840
|
|
|
840
841
|
|
|
841
842
|
def create_next_container_version(
|
|
842
843
|
container_pk: int,
|
|
843
844
|
*,
|
|
844
845
|
title: str | None,
|
|
845
|
-
|
|
846
|
-
entity_version_pks: list[int | None] | None,
|
|
846
|
+
entity_rows: list[ContainerEntityRow] | None,
|
|
847
847
|
created: datetime,
|
|
848
848
|
created_by: int | None,
|
|
849
849
|
container_version_cls: type[ContainerVersionModel] = ContainerVersion, # type: ignore[assignment]
|
|
@@ -863,8 +863,8 @@ def create_next_container_version(
|
|
|
863
863
|
Args:
|
|
864
864
|
container_pk: The ID of the container to create the next version of.
|
|
865
865
|
title: The title of the container. None to keep the current title.
|
|
866
|
-
|
|
867
|
-
|
|
866
|
+
entity_rows: List of ContainerEntityRows specifying the publishable entity ID and version ID (if pinned).
|
|
867
|
+
Or None for no change.
|
|
868
868
|
created: The date and time the container version was created.
|
|
869
869
|
created_by: The ID of the user who created the container version.
|
|
870
870
|
container_version_cls: The subclass of ContainerVersion to use, if applicable.
|
|
@@ -879,15 +879,15 @@ def create_next_container_version(
|
|
|
879
879
|
last_version = container.versioning.latest
|
|
880
880
|
assert last_version is not None
|
|
881
881
|
next_version_num = last_version.version_num + 1
|
|
882
|
-
|
|
882
|
+
|
|
883
|
+
if entity_rows is None:
|
|
883
884
|
# We're only changing metadata. Keep the same entity list.
|
|
884
885
|
next_entity_list = last_version.entity_list
|
|
885
886
|
else:
|
|
886
887
|
next_entity_list = create_next_entity_list(
|
|
887
888
|
entity.learning_package_id,
|
|
888
889
|
last_version,
|
|
889
|
-
|
|
890
|
-
entity_version_pks,
|
|
890
|
+
entity_rows,
|
|
891
891
|
entities_action
|
|
892
892
|
)
|
|
893
893
|
|
|
@@ -955,6 +955,21 @@ def get_containers(
|
|
|
955
955
|
return container_cls.objects.filter(publishable_entity__learning_package=learning_package_id)
|
|
956
956
|
|
|
957
957
|
|
|
958
|
+
def get_collection_containers(
|
|
959
|
+
learning_package_id: int,
|
|
960
|
+
collection_key: str,
|
|
961
|
+
) -> QuerySet[Container]:
|
|
962
|
+
"""
|
|
963
|
+
Returns a QuerySet of Containers relating to the PublishableEntities in a Collection.
|
|
964
|
+
|
|
965
|
+
Containers have a one-to-one relationship with PublishableEntity, but the reverse may not always be true.
|
|
966
|
+
"""
|
|
967
|
+
return Container.objects.filter(
|
|
968
|
+
publishable_entity__learning_package_id=learning_package_id,
|
|
969
|
+
publishable_entity__collections__key=collection_key,
|
|
970
|
+
).order_by('pk')
|
|
971
|
+
|
|
972
|
+
|
|
958
973
|
@dataclass(frozen=True)
|
|
959
974
|
class ContainerEntityListEntry:
|
|
960
975
|
"""
|
|
@@ -969,6 +984,23 @@ class ContainerEntityListEntry:
|
|
|
969
984
|
return self.entity_version.entity
|
|
970
985
|
|
|
971
986
|
|
|
987
|
+
@dataclass(frozen=True, kw_only=True, slots=True)
|
|
988
|
+
class ContainerEntityRow:
|
|
989
|
+
"""
|
|
990
|
+
[ 🛑 UNSTABLE ]
|
|
991
|
+
Used to specify the primary key of PublishableEntity and optional PublishableEntityVersion.
|
|
992
|
+
|
|
993
|
+
If version_pk is None (default), then the entity is considered "unpinned",
|
|
994
|
+
meaning that the latest version of the entity will be used.
|
|
995
|
+
"""
|
|
996
|
+
entity_pk: int
|
|
997
|
+
version_pk: int | None = None
|
|
998
|
+
|
|
999
|
+
@property
|
|
1000
|
+
def pinned(self):
|
|
1001
|
+
return self.entity_pk and self.version_pk is not None
|
|
1002
|
+
|
|
1003
|
+
|
|
972
1004
|
def get_entities_in_container(
|
|
973
1005
|
container: Container,
|
|
974
1006
|
*,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Generated by Django 5.2 on 2025-04-08 10:50
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('oel_publishing', '0004_publishableentity_can_stand_alone'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterModelOptions(
|
|
14
|
+
name='entitylistrow',
|
|
15
|
+
options={'ordering': ['order_num']},
|
|
16
|
+
),
|
|
17
|
+
]
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/api.py
RENAMED
|
@@ -62,8 +62,7 @@ def create_unit_version(
|
|
|
62
62
|
version_num: int,
|
|
63
63
|
*,
|
|
64
64
|
title: str,
|
|
65
|
-
|
|
66
|
-
entity_version_pks: list[int | None],
|
|
65
|
+
entity_rows: list[publishing_api.ContainerEntityRow],
|
|
67
66
|
created: datetime,
|
|
68
67
|
created_by: int | None = None,
|
|
69
68
|
) -> UnitVersion:
|
|
@@ -75,11 +74,10 @@ def create_unit_version(
|
|
|
75
74
|
`create_next_unit_version()` instead.
|
|
76
75
|
|
|
77
76
|
Args:
|
|
78
|
-
|
|
77
|
+
unit: The unit object.
|
|
79
78
|
version_num: The version number.
|
|
80
79
|
title: The title.
|
|
81
|
-
|
|
82
|
-
entity: The entity.
|
|
80
|
+
entity_rows: child entities/versions
|
|
83
81
|
created: The creation date.
|
|
84
82
|
created_by: The user who created the unit.
|
|
85
83
|
"""
|
|
@@ -87,8 +85,7 @@ def create_unit_version(
|
|
|
87
85
|
unit.pk,
|
|
88
86
|
version_num,
|
|
89
87
|
title=title,
|
|
90
|
-
|
|
91
|
-
entity_version_pks=entity_version_pks,
|
|
88
|
+
entity_rows=entity_rows,
|
|
92
89
|
created=created,
|
|
93
90
|
created_by=created_by,
|
|
94
91
|
container_version_cls=UnitVersion,
|
|
@@ -97,30 +94,34 @@ def create_unit_version(
|
|
|
97
94
|
|
|
98
95
|
def _pub_entities_for_components(
|
|
99
96
|
components: list[Component | ComponentVersion] | None,
|
|
100
|
-
) ->
|
|
97
|
+
) -> list[publishing_api.ContainerEntityRow] | None:
|
|
101
98
|
"""
|
|
102
99
|
Helper method: given a list of Component | ComponentVersion, return the
|
|
103
|
-
|
|
104
|
-
base container APIs.
|
|
100
|
+
list of ContainerEntityRows needed for the base container APIs.
|
|
105
101
|
|
|
106
102
|
ComponentVersion is passed when we want to pin a specific version, otherwise
|
|
107
103
|
Component is used for unpinned.
|
|
108
104
|
"""
|
|
109
105
|
if components is None:
|
|
110
106
|
# When these are None, that means don't change the entities in the list.
|
|
111
|
-
return None
|
|
107
|
+
return None
|
|
112
108
|
for c in components:
|
|
113
109
|
if not isinstance(c, (Component, ComponentVersion)):
|
|
114
110
|
raise TypeError("Unit components must be either Component or ComponentVersion.")
|
|
115
|
-
|
|
116
|
-
(
|
|
111
|
+
return [
|
|
112
|
+
(
|
|
113
|
+
publishing_api.ContainerEntityRow(
|
|
114
|
+
entity_pk=c.publishable_entity_id,
|
|
115
|
+
version_pk=None,
|
|
116
|
+
) if isinstance(c, Component)
|
|
117
|
+
else # isinstance(c, ComponentVersion)
|
|
118
|
+
publishing_api.ContainerEntityRow(
|
|
119
|
+
entity_pk=c.component.publishable_entity_id,
|
|
120
|
+
version_pk=c.pk,
|
|
121
|
+
)
|
|
122
|
+
)
|
|
117
123
|
for c in components
|
|
118
124
|
]
|
|
119
|
-
entity_version_pks = [
|
|
120
|
-
(cv.pk if isinstance(cv, ComponentVersion) else None)
|
|
121
|
-
for cv in components
|
|
122
|
-
]
|
|
123
|
-
return publishable_entities_pks, entity_version_pks
|
|
124
125
|
|
|
125
126
|
|
|
126
127
|
def create_next_unit_version(
|
|
@@ -143,12 +144,11 @@ def create_next_unit_version(
|
|
|
143
144
|
created: The creation date.
|
|
144
145
|
created_by: The user who created the unit.
|
|
145
146
|
"""
|
|
146
|
-
|
|
147
|
+
entity_rows = _pub_entities_for_components(components)
|
|
147
148
|
unit_version = publishing_api.create_next_container_version(
|
|
148
149
|
unit.pk,
|
|
149
150
|
title=title,
|
|
150
|
-
|
|
151
|
-
entity_version_pks=entity_version_pks,
|
|
151
|
+
entity_rows=entity_rows,
|
|
152
152
|
created=created,
|
|
153
153
|
created_by=created_by,
|
|
154
154
|
container_version_cls=UnitVersion,
|
|
@@ -177,7 +177,7 @@ def create_unit_and_version(
|
|
|
177
177
|
created_by: The user who created the unit.
|
|
178
178
|
can_stand_alone: Set to False when created as part of containers
|
|
179
179
|
"""
|
|
180
|
-
|
|
180
|
+
entity_rows = _pub_entities_for_components(components)
|
|
181
181
|
with atomic():
|
|
182
182
|
unit = create_unit(
|
|
183
183
|
learning_package_id,
|
|
@@ -190,8 +190,7 @@ def create_unit_and_version(
|
|
|
190
190
|
unit,
|
|
191
191
|
1,
|
|
192
192
|
title=title,
|
|
193
|
-
|
|
194
|
-
entity_version_pks=entity_version_pks or [],
|
|
193
|
+
entity_rows=entity_rows or [],
|
|
195
194
|
created=created,
|
|
196
195
|
created_by=created_by,
|
|
197
196
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openedx-learning
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: Open edX Learning Core and Tagging.
|
|
5
5
|
Home-page: https://github.com/openedx/openedx-learning
|
|
6
6
|
Author: David Ormsbee
|
|
@@ -10,6 +10,7 @@ Keywords: Python edx
|
|
|
10
10
|
Classifier: Development Status :: 3 - Alpha
|
|
11
11
|
Classifier: Framework :: Django
|
|
12
12
|
Classifier: Framework :: Django :: 4.2
|
|
13
|
+
Classifier: Framework :: Django :: 5.2
|
|
13
14
|
Classifier: Intended Audience :: Developers
|
|
14
15
|
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
15
16
|
Classifier: Natural Language :: English
|
|
@@ -18,12 +19,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
20
|
Requires-Python: >=3.11
|
|
20
21
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist:
|
|
22
|
+
Requires-Dist: attrs
|
|
22
23
|
Requires-Dist: rules<4.0
|
|
23
24
|
Requires-Dist: djangorestframework<4.0
|
|
24
|
-
Requires-Dist: Django<5.0
|
|
25
25
|
Requires-Dist: celery
|
|
26
|
-
Requires-Dist:
|
|
26
|
+
Requires-Dist: Django
|
|
27
|
+
Requires-Dist: edx-drf-extensions
|
|
27
28
|
Dynamic: author
|
|
28
29
|
Dynamic: author-email
|
|
29
30
|
Dynamic: classifier
|
|
@@ -55,6 +55,7 @@ openedx_learning/apps/authoring/publishing/migrations/0001_initial.py
|
|
|
55
55
|
openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py
|
|
56
56
|
openedx_learning/apps/authoring/publishing/migrations/0003_containers.py
|
|
57
57
|
openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py
|
|
58
|
+
openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py
|
|
58
59
|
openedx_learning/apps/authoring/publishing/migrations/__init__.py
|
|
59
60
|
openedx_learning/apps/authoring/publishing/models/__init__.py
|
|
60
61
|
openedx_learning/apps/authoring/publishing/models/container.py
|
|
@@ -5,7 +5,7 @@ attrs # Reduces boilerplate code involving class attributes
|
|
|
5
5
|
|
|
6
6
|
celery # Asynchronous task execution library
|
|
7
7
|
|
|
8
|
-
Django
|
|
8
|
+
Django # Web application framework
|
|
9
9
|
|
|
10
10
|
djangorestframework<4.0 # REST API
|
|
11
11
|
edx-drf-extensions # Extensions to the Django REST Framework used by Open edX
|
|
@@ -86,6 +86,7 @@ setup(
|
|
|
86
86
|
'Development Status :: 3 - Alpha',
|
|
87
87
|
'Framework :: Django',
|
|
88
88
|
'Framework :: Django :: 4.2',
|
|
89
|
+
'Framework :: Django :: 5.2',
|
|
89
90
|
'Intended Audience :: Developers',
|
|
90
91
|
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
|
|
91
92
|
'Natural Language :: English',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/api/authoring_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/api.py
RENAMED
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/contents/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/apps/authoring/units/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/apps.py
RENAMED
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/urls.py
RENAMED
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning/contrib/media_server/views.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_learning.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/__init__.py
RENAMED
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/models/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/urls.py
RENAMED
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.19.2 → openedx_learning-0.22.0}/openedx_tagging/core/tagging/rest_api/v1/urls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|