From e64facc731d52dc22c0f806ccce2a81628c393f0 Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Mon, 15 Sep 2025 09:01:49 +0200 Subject: [PATCH 1/3] [Fix] Skip inherited fields that don't exist in database MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add get_existing_fields() function to check database schema via introspection - Modify get_comments_for_model() to only process fields that exist in the database - Add test for model inheritance scenarios - Fixes errors when updating comments for inherited model fields 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- django_db_comments/db_comments.py | 23 +++++++++++++++++++++-- tests/test_db_comments.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/django_db_comments/db_comments.py b/django_db_comments/db_comments.py index 3771224..6d62b50 100644 --- a/django_db_comments/db_comments.py +++ b/django_db_comments/db_comments.py @@ -1,7 +1,7 @@ from psycopg2 import sql from django.apps import apps as global_apps -from django.db import DEFAULT_DB_ALIAS, router, connections, transaction +from django.db import DEFAULT_DB_ALIAS, router, connections, transaction, connection from django.conf import settings # django engines support @@ -24,10 +24,29 @@ POSTGRES_COMMENT_ON_TABLE_SQL = sql.SQL("COMMENT ON TABLE {} IS %s") +def get_existing_fields(model): + # Get the actual table name from the model + table_name = model._meta.db_table + + # Get a list of actual fields in the database table using introspection + with connection.cursor() as cursor: + query = """ + SELECT column_name + FROM information_schema.columns + WHERE table_name = %s; + """ + cursor.execute(query, [table_name]) + + existing_fields = {row[0] for row in cursor} + + valid_fields = [field for field in model._meta.fields if field.name in existing_fields]; + return valid_fields + + def get_comments_for_model(model): column_comments = {} - for field in model._meta.fields: + for field in get_existing_fields(model): comment = [] # Check if verbose name was not autogenerated, according to django code # https://github.com/django/django/blob/9681e96/django/db/models/fields/__init__.py#L724 diff --git a/tests/test_db_comments.py b/tests/test_db_comments.py index c316690..665a39b 100644 --- a/tests/test_db_comments.py +++ b/tests/test_db_comments.py @@ -52,6 +52,34 @@ class Meta: }, ) + def test_get_comments_for_model_with_inherited_fields(self): + class BaseModel(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + date_of_birth = models.DateField() + + class Meta: + app_label = "unit_test" + + class InheritingModel(BaseModel): + no_comment = models.TextField() + verbose_name = models.TextField("This is a verbose name") + help_text = models.TextField( + help_text="I really should see this in the database" + ) + + class Meta: + app_label = "unit_test" + + column_comments = get_comments_for_model(InheritingModel) + self.assertDictEqual( + column_comments, + { + "verbose_name": "This is a verbose name", + "help_text": "I really should see this in the database", + }, + ) + @patch("django_db_comments.db_comments.connections") def test_add_column_comments_to_database(self, mock_connections): mock_cursor = mock_connections.__getitem__( From 18cef1545c9faf8842da793d46c48582452a3e55 Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Mon, 15 Sep 2025 09:20:06 +0200 Subject: [PATCH 2/3] fix: minimize changes --- django_db_comments/db_comments.py | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/django_db_comments/db_comments.py b/django_db_comments/db_comments.py index 6d62b50..c86571a 100644 --- a/django_db_comments/db_comments.py +++ b/django_db_comments/db_comments.py @@ -24,29 +24,10 @@ POSTGRES_COMMENT_ON_TABLE_SQL = sql.SQL("COMMENT ON TABLE {} IS %s") -def get_existing_fields(model): - # Get the actual table name from the model - table_name = model._meta.db_table - - # Get a list of actual fields in the database table using introspection - with connection.cursor() as cursor: - query = """ - SELECT column_name - FROM information_schema.columns - WHERE table_name = %s; - """ - cursor.execute(query, [table_name]) - - existing_fields = {row[0] for row in cursor} - - valid_fields = [field for field in model._meta.fields if field.name in existing_fields]; - return valid_fields - - def get_comments_for_model(model): column_comments = {} - for field in get_existing_fields(model): + for field in model._meta.fields: comment = [] # Check if verbose name was not autogenerated, according to django code # https://github.com/django/django/blob/9681e96/django/db/models/fields/__init__.py#L724 @@ -115,7 +96,7 @@ def copy_help_texts_to_database( app_models = [ app_model - for app_model in app_config.get_models() + for app_model in apps.get_models() if not any( [ app_model._meta.abstract, From a7266f24cfe9f9b0489b33816213c5841c5addba Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Mon, 15 Sep 2025 09:22:59 +0200 Subject: [PATCH 3/3] Update test_db_comments.py --- tests/test_db_comments.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/tests/test_db_comments.py b/tests/test_db_comments.py index 665a39b..c316690 100644 --- a/tests/test_db_comments.py +++ b/tests/test_db_comments.py @@ -52,34 +52,6 @@ class Meta: }, ) - def test_get_comments_for_model_with_inherited_fields(self): - class BaseModel(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - date_of_birth = models.DateField() - - class Meta: - app_label = "unit_test" - - class InheritingModel(BaseModel): - no_comment = models.TextField() - verbose_name = models.TextField("This is a verbose name") - help_text = models.TextField( - help_text="I really should see this in the database" - ) - - class Meta: - app_label = "unit_test" - - column_comments = get_comments_for_model(InheritingModel) - self.assertDictEqual( - column_comments, - { - "verbose_name": "This is a verbose name", - "help_text": "I really should see this in the database", - }, - ) - @patch("django_db_comments.db_comments.connections") def test_add_column_comments_to_database(self, mock_connections): mock_cursor = mock_connections.__getitem__(