Repository navigation
feat: adds content tagging app, models, and API #32518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 3 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
2f70278
feat: adds content tagging app, models, admin, and API
pomegranited d27c18c
refactor: moves is_content_creator
pomegranited 456979a
feat: adds permissions/rules for content_tagging
pomegranited 3ade910
style: group tagging INSTALLED_APPS together
pomegranited d51e148
perf: rearrange ContentTaxonomy.validate_object_tag
pomegranited d0c446b
style: import oel_tagging API methods more concisely
pomegranited a0e33e1
style: adds type annotations to rules
pomegranited 7278da0
fix: filter ContentTaxonomies by org, independent of the enabled flag
pomegranited 4f297f6
fix: use InheritanceManager in oel_tagging
pomegranited df61b49
Merge branch 'master' into jill/add-content-tagging
pomegranited File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| """ Tagging app admin """ | ||
| from django.contrib import admin | ||
|
|
||
| from .models import ContentTaxonomy | ||
|
|
||
|
|
||
| class ContentTaxonomyOrgAdmin(admin.TabularInline): | ||
| model = ContentTaxonomy.org_owners.through | ||
|
|
||
|
|
||
| class ContentTaxonomyAdmin(admin.ModelAdmin): | ||
| """ | ||
| Admin form for the content taxonomy table. | ||
| """ | ||
|
|
||
| inlines = (ContentTaxonomyOrgAdmin,) | ||
|
|
||
|
|
||
| admin.site.register(ContentTaxonomy, ContentTaxonomyAdmin) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| """ | ||
| Content Tagging APIs | ||
| """ | ||
| from typing import List | ||
|
|
||
| import openedx_tagging.core.tagging.api as oel_tagging | ||
| from django.db.models import QuerySet | ||
| from openedx_tagging.core.tagging.models import ObjectTag, Tag, Taxonomy | ||
| from organizations.models import Organization | ||
|
|
||
| from .models import ContentTaxonomy | ||
|
|
||
|
|
||
| def create_taxonomy( | ||
| name, | ||
| org_owners: List[Organization] = None, | ||
| description=None, | ||
| enabled=True, | ||
| required=False, | ||
| allow_multiple=False, | ||
| allow_free_text=False, | ||
| ) -> ContentTaxonomy: | ||
| """ | ||
| Creates, saves, and returns a new ContentTaxonomy with the given attributes. | ||
|
|
||
| If `org_owners` is empty/None, then the returned taxonomy is enabled for all organizations. | ||
| """ | ||
| taxonomy = ContentTaxonomy.objects.create( | ||
| name=name, | ||
| description=description, | ||
| enabled=enabled, | ||
| required=required, | ||
| allow_multiple=allow_multiple, | ||
| allow_free_text=allow_free_text, | ||
| ) | ||
| if org_owners: | ||
| set_taxonomy_org_owners(taxonomy, org_owners) | ||
| return taxonomy | ||
|
|
||
|
|
||
| def set_taxonomy_org_owners( | ||
| taxonomy: ContentTaxonomy, | ||
| org_owners: List[Organization] = None, | ||
| ) -> ContentTaxonomy: | ||
| """ | ||
| Updates the list of org_owners on the given taxonomy. | ||
|
|
||
| If `org_owners` is empty/None, then the returned taxonomy is enabled for all organizations. | ||
| """ | ||
| if org_owners: | ||
| taxonomy.org_owners.set(org_owners) | ||
| else: | ||
| taxonomy.org_owners.clear() | ||
| return taxonomy | ||
|
|
||
|
|
||
| def get_taxonomies(org_owner: Organization = None, enabled=True) -> QuerySet: | ||
| """ | ||
| Returns a queryset containing the enabled taxonomies owned by the given org, sorted by name. | ||
|
|
||
| If you want the disabled taxonomies, pass enabled=False. | ||
| If you want all taxonomies (both enabled and disabled), pass enabled=None. | ||
| """ | ||
| return ( | ||
| ContentTaxonomy.objects.filter_enabled( | ||
| org_owner, | ||
| enabled, | ||
| ) | ||
| .order_by("name", "id") | ||
| .select_subclasses() | ||
| ) | ||
|
|
||
|
|
||
| # Expose the oel_tagging APIs | ||
|
pomegranited marked this conversation as resolved.
Resolved
|
||
|
|
||
|
|
||
| def get_tags(taxonomy: Taxonomy) -> List[Tag]: | ||
| """ | ||
| Exposes the oel_tagging.get_tags API method. | ||
| """ | ||
| return oel_tagging.get_tags(taxonomy) | ||
|
|
||
|
|
||
| def resync_object_tags(object_tags: QuerySet = None) -> int: | ||
| """ | ||
| Exposes the oel_tagging.resync_object_tags API method. | ||
| """ | ||
| return oel_tagging.resync_object_tags(object_tags) | ||
|
|
||
|
|
||
| def get_object_tags( | ||
| taxonomy: Taxonomy, object_id: str, object_type: str, valid_only=True | ||
| ) -> List[ObjectTag]: | ||
| """ | ||
| Exposes the oel_tagging.get_object_tags API method. | ||
| """ | ||
| return oel_tagging.get_object_tags(taxonomy, object_id, object_type, valid_only) | ||
|
|
||
|
|
||
| def tag_object( | ||
| taxonomy: Taxonomy, tags: List, object_id: str, object_type: str | ||
| ) -> List[ObjectTag]: | ||
| """ | ||
| Exposes the oel_tagging.tag_object API method. | ||
| """ | ||
| return oel_tagging.tag_object(taxonomy, tags, object_id, object_type) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| """ | ||
| Define the content tagging Django App. | ||
| """ | ||
|
|
||
| from django.apps import AppConfig | ||
|
|
||
|
|
||
| class ContentTaggingConfig(AppConfig): | ||
| """App config for the content tagging feature""" | ||
|
|
||
| default_auto_field = "django.db.models.BigAutoField" | ||
| name = "openedx.features.content_tagging" |
72 changes: 72 additions & 0 deletions
72
openedx/features/content_tagging/migrations/0001_initial.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Generated by Django 3.2.19 on 2023-06-19 22:44 | ||
|
|
||
| from django.db import migrations, models | ||
| import django.db.models.deletion | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| initial = True | ||
|
|
||
| dependencies = [ | ||
| ("organizations", "0003_historicalorganizationcourse"), | ||
| ("oel_tagging", "0001_initial"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.CreateModel( | ||
| name="ContentTaxonomy", | ||
| fields=[ | ||
| ( | ||
| "taxonomy_ptr", | ||
| models.OneToOneField( | ||
| auto_created=True, | ||
| on_delete=django.db.models.deletion.CASCADE, | ||
| parent_link=True, | ||
| primary_key=True, | ||
| serialize=False, | ||
| to="oel_tagging.taxonomy", | ||
| ), | ||
| ), | ||
| ], | ||
| options={ | ||
| "verbose_name_plural": "ContentTaxonomies", | ||
| }, | ||
| bases=("oel_tagging.taxonomy",), | ||
| ), | ||
| migrations.CreateModel( | ||
| name="ContentTaxonomyOrg", | ||
| fields=[ | ||
| ( | ||
| "id", | ||
| models.BigAutoField( | ||
| auto_created=True, | ||
| primary_key=True, | ||
| serialize=False, | ||
| verbose_name="ID", | ||
| ), | ||
| ), | ||
| ( | ||
| "org", | ||
| models.ForeignKey( | ||
| on_delete=django.db.models.deletion.CASCADE, | ||
| to="organizations.organization", | ||
| ), | ||
| ), | ||
| ( | ||
| "taxonomy", | ||
| models.ForeignKey( | ||
| on_delete=django.db.models.deletion.CASCADE, | ||
| to="content_tagging.contenttaxonomy", | ||
| ), | ||
| ), | ||
| ], | ||
| ), | ||
| migrations.AddField( | ||
| model_name="contenttaxonomy", | ||
| name="org_owners", | ||
| field=models.ManyToManyField( | ||
| through="content_tagging.ContentTaxonomyOrg", | ||
| to="organizations.Organization", | ||
| ), | ||
| ), | ||
| ] |
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.