diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bd7b0897..39df10cb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,8 @@ Unreleased ********** * Add support for Typesense as the search backend. +* Fix: Set default value for ``pinned`` field on ``CommentThread`` to ``False`` + to prevent NULL sort bug. 0.3.4 – 2025-08-13 ****************** diff --git a/forum/__init__.py b/forum/__init__.py index bc1fa6c4..255a215f 100644 --- a/forum/__init__.py +++ b/forum/__init__.py @@ -2,4 +2,4 @@ Openedx forum app. """ -__version__ = "0.4.0" +__version__ = "0.4.1" diff --git a/forum/backends/mysql/api.py b/forum/backends/mysql/api.py index b115119b..c383d31a 100644 --- a/forum/backends/mysql/api.py +++ b/forum/backends/mysql/api.py @@ -1865,6 +1865,7 @@ def create_thread(data: dict[str, Any]) -> str: thread_type=data.get("thread_type", "discussion"), context=data.get("context", "course"), last_activity_at=timezone.now(), + pinned=data.get("pinned", False), **optional_args, ) return str(new_thread.pk) diff --git a/forum/backends/mysql/models.py b/forum/backends/mysql/models.py index 3924a0d6..211d1ff5 100644 --- a/forum/backends/mysql/models.py +++ b/forum/backends/mysql/models.py @@ -239,7 +239,7 @@ class CommentThread(Content): ) closed: models.BooleanField[bool, bool] = models.BooleanField(default=False) pinned: models.BooleanField[Optional[bool], bool] = models.BooleanField( - null=True, blank=True + default=False ) last_activity_at: models.DateTimeField[Optional[datetime], datetime] = ( models.DateTimeField(null=True, blank=True) diff --git a/forum/migration_helpers.py b/forum/migration_helpers.py index f47d5672..fb3a79a9 100644 --- a/forum/migration_helpers.py +++ b/forum/migration_helpers.py @@ -122,7 +122,7 @@ def create_or_update_thread(thread_data: dict[str, Any]) -> None: anonymous=thread_data.get("anonymous", False), anonymous_to_peers=thread_data.get("anonymous_to_peers", False), closed=thread_data.get("closed", False), - pinned=thread_data.get("pinned"), + pinned=thread_data.get("pinned", False), last_activity_at=make_aware(thread_data["last_activity_at"]), commentable_id=thread_data.get("commentable_id"), ) diff --git a/forum/migrations/0005_alter_commentthread_pinned.py b/forum/migrations/0005_alter_commentthread_pinned.py new file mode 100644 index 00000000..c95ebcc6 --- /dev/null +++ b/forum/migrations/0005_alter_commentthread_pinned.py @@ -0,0 +1,26 @@ +# Generated by Django 5.2.12 on 2026-03-27 06:58 + +from typing import Any + +from django.db import migrations, models + + +def backfill_pinned_false(apps: Any, schema_editor: Any) -> None: + CommentThread = apps.get_model("forum", "CommentThread") + CommentThread.objects.filter(pinned__isnull=True).update(pinned=False) + + +class Migration(migrations.Migration): + + dependencies = [ + ("forum", "0004_add_author_username_fields"), + ] + + operations = [ + migrations.RunPython(backfill_pinned_false, migrations.RunPython.noop), + migrations.AlterField( + model_name="commentthread", + name="pinned", + field=models.BooleanField(default=False), + ), + ] diff --git a/tests/test_backends/test_mysql/test_models.py b/tests/test_backends/test_mysql/test_models.py index f483970e..6598c13a 100644 --- a/tests/test_backends/test_mysql/test_models.py +++ b/tests/test_backends/test_mysql/test_models.py @@ -106,7 +106,7 @@ def test_comment_thread_creation() -> None: assert comment_thread.thread_type == "discussion" assert comment_thread.context == "course" assert comment_thread.closed is False - assert comment_thread.pinned is None + assert comment_thread.pinned is False @pytest.mark.django_db