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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ requirements/private.txt
dev.db*

.vscode
venv/

# Media files (for uploads)
media/
Empty file.
5 changes: 5 additions & 0 deletions openedx_learning/contrib/tagging/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
""" Tagging app admin """
from django.contrib import admin
from .models import TagContent

admin.site.register(TagContent)
16 changes: 16 additions & 0 deletions openedx_learning/contrib/tagging/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
tagging Django application initialization.
"""

from django.apps import AppConfig


class TaggingConfig(AppConfig):
"""
Configuration for the tagging Django application.
"""

name = "openedx_learning.contrib.tagging"
verbose_name = "Tagging"
default_auto_field = 'django.db.models.BigAutoField'
label = "oel_tagging"
23 changes: 23 additions & 0 deletions openedx_learning/contrib/tagging/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.19 on 2023-05-25 21:08

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='TagContent',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content_id', models.CharField(max_length=255)),
('name', models.CharField(max_length=255)),
('value', models.CharField(max_length=765)),
],
),
]
Empty file.
38 changes: 38 additions & 0 deletions openedx_learning/contrib/tagging/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
""" Tagging app data models """
from django.db import models

class TagContent(models.Model):
"""
TODO: This is a basic representation of TagContent, it may change
depending on the discovery in:
https://docs.google.com/document/d/13zfsGDfomSTCp_G-_ncevQHAb4Y4UW0d_6N8R2PdHlA/edit#heading=h.o6fm1hktwp7b

This is the representation of a tag that is linked to a content

Name-Value pair
-----------------

We use a Field-Value Pair representation, where `name` functions
as the constant that defines the field data set, and `value` functions
as the variable tag lineage that belong to the set.

Value lineage
---------------

`value` are stored as null character-delimited strings to preserve the tag's lineage.
We use the null character to avoid choosing a character that may exist in a tag's name.
We don't use the Taxonomy's user-facing delimiter so that this delimiter can be changed
without disrupting stored tags.
"""

# Content id to which this tag is associated
content_id = models.CharField(max_length=255)

# It's not usually large
name = models.CharField(max_length=255)

# Tag lineage value.
#
# The lineage can be large.
# TODO: The length is under discussion
value = models.CharField(max_length=765)
26 changes: 26 additions & 0 deletions openedx_learning/contrib/tagging/readme.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Tagging App
==============

The ``tagging`` app will enable content authors to tag pieces of content and quickly
filter for ease of re-use.

Motivation
----------

Tagging content is central to enable content re-use, facilitate the implementation
of flexible content structures different from the current implementation and
allow adaptive learning in the Open edX platform.

This service has been implemented as pluggable django app. Since it is necessary for
it to work independently of the content to which it links to.

Setup
---------

**TODO:** We need to wait the discussion of the `Taxonomy discovery <https://docs.google.com/document/d/13zfsGDfomSTCp_G-_ncevQHAb4Y4UW0d_6N8R2PdHlA/edit#heading=h.o6fm1hktwp7b>`_.
to build a proper setup for linking different pieces of content.

The current approach is to save the id of the content through a generic string,
so that the tag can be linked to any type of content, no matter what type of ID have.
For example, with this approach we can link standalone blocks and library blocks,
both on Denver (v3) and Blockstore Content Libraries (v2).
1 change: 1 addition & 0 deletions projects/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"openedx_learning.core.publishing.apps.PublishingConfig",
# Learning Contrib Apps
"openedx_learning.contrib.media_server.apps.MediaServerConfig",
"openedx_learning.contrib.tagging.apps.TaggingConfig",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. this tagging app is supposed to be a "plugin", which to me means:

  1. it's installed alongside edx-django-utils whose plugin utils which ensures that it gets automatically added to the INSTALLED_APPS list in the right context
  2. it can be installed separately into apps where needed, and

edx-django-utils is specifically tailored to the lms and cms apps in edx-platform, and doesn't have an equivalent on this app, so..

Maybe we need to deal with the "pluggability" aspect when it comes time to extract this app out for reuse outside of openedx-learning?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pomegranited Good point! I didn't account for edx-django-utils for this. I have taken into account that it had to be "installed alongside learning-core as a dependency in the edx-platform"

Another option would be to build this app to be installed alongside edx-django-utils so that we can use them with the current open-edx content and install it as a direct dependency on learning-core when we used the learning-core content. The problem is that I don't know how complicated this approach is in the long run.

Maybe we need to deal with the "pluggability" aspect when it comes time to extract this app out for reuse outside of openedx-learning?

I will leave this as an open question

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need to deal with the "pluggability" aspect when it comes time to extract this app out for reuse outside of openedx-learning?

Yeah, I think this is something that we can address later. I don't think it needs to be a plugin-utils styled plugin, but more of a library-style app that handles tagging related concerns and is used by our other apps. But I do think this means that the tagging functionality modeling in this repo should be split up so that there is:

  1. An app or group of tagging-related apps that is entirely self contained, i.e. has no foreign keys to anything in the openedx_learning package. If we're pretty confident that this is going to be its own top level thing that will eventually be used in other parts of the platform, we should give it its own top level package, e.g. openedx_tagging (or some other unique name that we can eventually register on PyPI).
  2. The openedx_learning.contrib.tagging app, which would be where we apply tagging to openedx_learning models like PublishableEntity and PublishableEntityVersion. This would probably stay in this repo over the long term.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be to build this app to be installed alongside edx-django-utils so that we can use them with the current open-edx content and install it as a direct dependency on learning-core when we used the learning-core content. The problem is that I don't know how complicated this approach is in the long run.

Didn't see this reply when I wrote my message. I like this approach.

@pomegranited pomegranited May 30, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be to build this app to be installed alongside edx-django-utils

I like this approach too, but it has the limitation that edx-django-utils is specifically tailored to edx-platform -- i.e., you can currently only register plugins for "lms" and "cms" -- so we'd need to enhance it to also register plugins for learning core.

So I'd rather not convert this into a plugin right now, but plan for it by respecting the encapsulation @ormsbee laid out above:

  • move this to a new openedx_tagging package in this repo, sibling of openedx_learning
  • openedx_tagging has no foreign keys to anything in the openedx_learning package
  • openedx_learning.contrib.tagging contains any models that need to link the two packages.

@ChrisChV I'm happy to do this move as part of the data architecture ADR which is coming this week, ref openedx/modular-learning#60

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach 👍

@ChrisChV I'm happy to do this move as part of the data architecture ADR which is coming this week, ref openedx/modular-learning#60

Sure, thanks @pomegranited 👍

# Apps that don't belong in this repo in the long term, but are here to make
# testing/iteration easier until the APIs stabilize.
"olx_importer.apps.OLXImporterConfig",
Expand Down