From 582089c33931f8690d8773928e3d3811b9469205 Mon Sep 17 00:00:00 2001 From: Andrii Date: Mon, 23 Jun 2025 16:54:43 +0300 Subject: [PATCH 1/3] feat: add new field for Content-/UserDate models to support assignments --- ..._title_contentdate_course_name_and_more.py | 55 +++++++++++++++++++ edx_when/models.py | 32 +++++++++++ 2 files changed, 87 insertions(+) create mode 100644 edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py diff --git a/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py new file mode 100644 index 00000000..2f21675f --- /dev/null +++ b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 4.2.22 on 2025-06-23 13:56 + +import opaque_keys.edx.django.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edx_when', '0008_courseversion_block_type'), + ] + + operations = [ + migrations.AddField( + model_name='contentdate', + name='assignment_title', + field=models.CharField(blank=True, db_index=True, default='', max_length=255), + ), + migrations.AddField( + model_name='contentdate', + name='course_name', + field=models.CharField(blank=True, default='', max_length=255), + ), + migrations.AddField( + model_name='contentdate', + name='subsection_name', + field=models.CharField(blank=True, db_index=True, default='', max_length=255), + ), + migrations.AddField( + model_name='userdate', + name='first_component_block_id', + field=opaque_keys.edx.django.models.UsageKeyField(blank=True, db_index=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='userdate', + name='user_date_value', + field=models.DateTimeField(blank=True, db_index=True, null=True), + ), + migrations.AddIndex( + model_name='contentdate', + index=models.Index(fields=['assignment_title', 'course_id'], name='edx_when_assignment_course_idx'), + ), + migrations.AddIndex( + model_name='contentdate', + index=models.Index(fields=['subsection_name', 'course_id'], name='edx_when_subsection_course_idx'), + ), + migrations.AddIndex( + model_name='userdate', + index=models.Index(fields=['user', 'first_component_block_id'], name='edx_when_user_first_block_idx'), + ), + migrations.AddIndex( + model_name='userdate', + index=models.Index(fields=['user_date_value', 'user'], name='edx_when_user_date_value_idx'), + ), + ] diff --git a/edx_when/models.py b/edx_when/models.py index e540bdfa..98315ee3 100644 --- a/edx_when/models.py +++ b/edx_when/models.py @@ -93,6 +93,9 @@ class ContentDate(models.Model): field = models.CharField(max_length=255, default='') active = models.BooleanField(default=True) block_type = models.CharField(max_length=255, null=True) + assignment_title = models.CharField(max_length=255, blank=True, default='', db_index=True) + course_name = models.CharField(max_length=255, blank=True, default='') + subsection_name = models.CharField(max_length=255, blank=True, default='', db_index=True) class Meta: """Django Metadata.""" @@ -100,6 +103,8 @@ class Meta: unique_together = ('policy', 'location', 'field') indexes = [ models.Index(fields=('course_id', 'block_type'), name='edx_when_course_block_type_idx'), + models.Index(fields=('assignment_title', 'course_id'), name='edx_when_assignment_course_idx'), + models.Index(fields=('subsection_name', 'course_id'), name='edx_when_subsection_course_idx'), ] def __str__(self): @@ -109,6 +114,14 @@ def __str__(self): # Location already holds course id return f'ContentDate({self.policy}, {self.location}, {self.field}, {self.block_type})' + def __repr__(self): + """ + Get a detailed representation of this model instance. + """ + return (f'ContentDate(id={self.id}, assignment_title="{self.assignment_title}", ' + f'course_name="{self.course_name}", subsection_name="{self.subsection_name}", ' + f'policy={self.policy}, location={self.location})') + class UserDate(TimeStampedModel): """ @@ -125,6 +138,16 @@ class UserDate(TimeStampedModel): actor = models.ForeignKey( get_user_model(), null=True, default=None, blank=True, related_name="actor", on_delete=models.CASCADE ) + first_component_block_id = UsageKeyField(null=True, blank=True, max_length=255, db_index=True) + user_date_value = models.DateTimeField(null=True, blank=True, db_index=True) + + class Meta: + """Django Metadata.""" + + indexes = [ + models.Index(fields=('user', 'first_component_block_id'), name='edx_when_user_first_block_idx'), + models.Index(fields=('user_date_value', 'user'), name='edx_when_user_date_value_idx'), + ] @property def actual_date(self): @@ -169,3 +192,12 @@ def __str__(self): # Location already holds course id # pylint: disable=no-member return f'{self.user.username}, {self.content_date.location}, {self.content_date.field}' + + def __repr__(self): + """ + Get a detailed representation of this model instance. + """ + # pylint: disable=no-member + return (f'UserDate(id={self.id}, user="{self.user.username}", ' + f'first_component_block_id={self.first_component_block_id}, ' + f'user_date_value={self.user_date_value}, content_date={self.content_date.id})') From a15bbd56e1beca9cb9febe76969e97b530f34250 Mon Sep 17 00:00:00 2001 From: Serhii Nanai Date: Wed, 20 Aug 2025 12:14:34 +0300 Subject: [PATCH 2/3] fix: remove user_date_value, recreate 0009 migration --- ...gnment_title_contentdate_course_name_and_more.py | 13 ++----------- edx_when/models.py | 4 +--- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py index 2f21675f..f664107a 100644 --- a/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py +++ b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py @@ -1,7 +1,7 @@ -# Generated by Django 4.2.22 on 2025-06-23 13:56 +# Generated by Django 4.2.22 on 2025-08-20 09:11 -import opaque_keys.edx.django.models from django.db import migrations, models +import opaque_keys.edx.django.models class Migration(migrations.Migration): @@ -31,11 +31,6 @@ class Migration(migrations.Migration): name='first_component_block_id', field=opaque_keys.edx.django.models.UsageKeyField(blank=True, db_index=True, max_length=255, null=True), ), - migrations.AddField( - model_name='userdate', - name='user_date_value', - field=models.DateTimeField(blank=True, db_index=True, null=True), - ), migrations.AddIndex( model_name='contentdate', index=models.Index(fields=['assignment_title', 'course_id'], name='edx_when_assignment_course_idx'), @@ -48,8 +43,4 @@ class Migration(migrations.Migration): model_name='userdate', index=models.Index(fields=['user', 'first_component_block_id'], name='edx_when_user_first_block_idx'), ), - migrations.AddIndex( - model_name='userdate', - index=models.Index(fields=['user_date_value', 'user'], name='edx_when_user_date_value_idx'), - ), ] diff --git a/edx_when/models.py b/edx_when/models.py index 98315ee3..55653cfa 100644 --- a/edx_when/models.py +++ b/edx_when/models.py @@ -139,14 +139,12 @@ class UserDate(TimeStampedModel): get_user_model(), null=True, default=None, blank=True, related_name="actor", on_delete=models.CASCADE ) first_component_block_id = UsageKeyField(null=True, blank=True, max_length=255, db_index=True) - user_date_value = models.DateTimeField(null=True, blank=True, db_index=True) class Meta: """Django Metadata.""" indexes = [ models.Index(fields=('user', 'first_component_block_id'), name='edx_when_user_first_block_idx'), - models.Index(fields=('user_date_value', 'user'), name='edx_when_user_date_value_idx'), ] @property @@ -200,4 +198,4 @@ def __repr__(self): # pylint: disable=no-member return (f'UserDate(id={self.id}, user="{self.user.username}", ' f'first_component_block_id={self.first_component_block_id}, ' - f'user_date_value={self.user_date_value}, content_date={self.content_date.id})') + f'content_date={self.content_date.id})') From 9f4308aabb5967da80b20d76687169e526755934 Mon Sep 17 00:00:00 2001 From: Serhii Nanai Date: Wed, 27 Aug 2025 11:44:01 +0300 Subject: [PATCH 3/3] fix: fix imports order in 0009 migration --- ...entdate_assignment_title_contentdate_course_name_and_more.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py index f664107a..ad87bcf7 100644 --- a/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py +++ b/edx_when/migrations/0009_contentdate_assignment_title_contentdate_course_name_and_more.py @@ -1,7 +1,7 @@ # Generated by Django 4.2.22 on 2025-08-20 09:11 -from django.db import migrations, models import opaque_keys.edx.django.models +from django.db import migrations, models class Migration(migrations.Migration):