Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions openedx_tagging/core/tagging/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Please look at the models.py file for more information about the kinds of data
are stored in this app.
"""
from typing import List, Type, Union
from typing import Generator, List, Type, Union

from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
Expand All @@ -19,24 +19,29 @@


def create_taxonomy(
name,
description=None,
name: str,
description: str = None,
enabled=True,
required=False,
allow_multiple=False,
allow_free_text=False,
object_tag_class: Type = None,
) -> Taxonomy:
"""
Creates, saves, and returns a new Taxonomy with the given attributes.
"""
return Taxonomy.objects.create(
taxonomy = Taxonomy(
name=name,
description=description,
enabled=enabled,
required=required,
allow_multiple=allow_multiple,
allow_free_text=allow_free_text,
)
if object_tag_class:
taxonomy.object_tag_class = object_tag_class
taxonomy.save()
return taxonomy


def get_taxonomies(enabled=True) -> QuerySet:
Expand Down Expand Up @@ -86,18 +91,33 @@ def resync_object_tags(object_tags: QuerySet = None) -> int:


def get_object_tags(
taxonomy: Taxonomy, object_id: str, object_type: str, valid_only=True
) -> List[ObjectTag]:
object_id: str, object_type: str = None, taxonomy: Taxonomy = None, valid_only=True
) -> Generator[ObjectTag, None, None]:
"""
Returns a list of tags for a given taxonomy + content.
Generates a list of object tags for a given object.

Pass taxonomy to limit the returned object_tags to a specific taxonomy.

Pass valid_only=False when displaying tags to content authors, so they can see invalid tags too.
Invalid tags will likely be hidden from learners.
Invalid tags will (probably) be hidden from learners.
"""
tags = taxonomy.objecttag_set.filter(
object_id=object_id, object_type=object_type
tags = ObjectTag.objects.filter(
object_id=object_id,
).order_by("id")
return [tag for tag in tags if not valid_only or taxonomy.validate_object_tag(tag)]
if object_type:
tags = tags.filter(object_type=object_type)
if taxonomy:
tags = tags.filter(_taxonomy=taxonomy)

for tag in tags:
# We can only validate tags with taxonomies, because we need the object_tag_class
if valid_only:
if tag._taxonomy_id:
object_tag = tag.taxonomy.object_tag_class().copy(tag)
if object_tag.is_valid():
yield object_tag
else:
yield tag


def tag_object(
Expand Down
41 changes: 41 additions & 0 deletions openedx_tagging/core/tagging/migrations/0004_objecttagclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 3.2.19 on 2023-07-04 07:24

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("oel_tagging", "0003_objecttag__taxonomy"),
]

operations = [
migrations.CreateModel(
name="OpenObjectTag",
fields=[],
options={
"proxy": True,
"indexes": [],
"constraints": [],
},
bases=("oel_tagging.objecttag",),
),
migrations.AddField(
model_name="taxonomy",
name="_object_tag_class",
field=models.CharField(
help_text="Overrides the default BaseObjectTag subclass associated with this taxonomy.Must be a fully-qualified module and class name.",
max_length=255,
null=True,
),
),
migrations.CreateModel(
name="ClosedObjectTag",
fields=[],
options={
"proxy": True,
"indexes": [],
"constraints": [],
},
bases=("oel_tagging.openobjecttag",),
),
]
Loading