Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"makeviewmigrations --check --dry-run" fails when using "ContentType" in auto-generated DB View migrations on an unmigrated database #44

Open
gabo-magnet opened this issue Feb 3, 2025 · 2 comments

Comments

@gabo-magnet
Copy link

When using django_db_views to generate database view migrations that rely on django.contrib.contenttypes.models.ContentType, running python manage.py makeviewmigrations --check --dry-run on a fresh database (without applying migrations) results in the following error:

psycopg.errors.UndefinedTable: relation "django_content_type" does not exist

This issue occurs because the auto-generated migration includes a query that references the django_content_type table, which does not exist in a freshly migrated database. Since CI/CD pipelines often use makeviewmigrations --check --dry-run to verify pending migrations without applying them, this leads to an unexpected failure.

Steps to Reproduce:

  1. Install django_db_views in a Django project.
  2. Create a DBView model that references ContentType in a query.
  3. Allow django_db_views to auto-generate a migration that includes this model.
  4. Run python manage.py makeviewmigrations --check --dry-run on a fresh database.

Example Code:

DB View Model Using ContentType

from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import F, Value
from django_db_views.db_view import DBView

class ExampleDBView(DBView):
    @classmethod
    def view_definition(cls):
        queryset = (
            ExampleModel.objects.annotate(
                object_id=F("id"),
                content_type_id=Value(ContentType.objects.get_for_model(ExampleModel).id)
            ).values("object_id", "content_type_id")
        )
        return str(queryset.query)

    class Meta:
        managed = False
        db_table = "example_db_view"

In this example, the view relies on ContentType.objects.get_for_model() to include the content_type_id in the query. The auto-generated migration from django_db_views will include a ViewRunPython operation with this query.

Auto-Generated Migration (example of what might be auto-generated)

from django.db import migrations
import django_db_views.migration_functions
import django_db_views.operations

class Migration(migrations.Migration):
    dependencies = [
        ("contenttypes", "0002_remove_content_type_name"), # added this by hand
    ]

    operations = [
        django_db_views.operations.ViewRunPython(
            code=django_db_views.migration_functions.ForwardViewMigration(
                '...'
                "example_db_view",
                engine="django.db.backends.postgresql",
            ),
            reverse_code=django_db_views.migration_functions.BackwardViewMigration(
                "",
                "example_db_view",
                engine="django.db.backends.postgresql",
            ),
            atomic=False,
        ),
    ]

Expected Behavior:

  • makeviewmigrations --check --dry-run should not fail if the contenttypes app has not yet been migrated.

Actual Behavior:

Running makeviewmigrations --check --dry-run results in a ProgrammingError because the django_content_type table is missing, as the database has not been migrated yet.

Workarounds Tried:

  • Ensuring that contenttypes is included in the migration dependencies (did not solve the issue).
  • Running migrate before makeviewmigrations --check --dry-run (works but defeats the purpose of checking migrations in CI).

Environment:

  • Django version: 4.2.16
  • Python version: 3.10.16
  • Database: PostgreSQL
  • django-db-views version: 0.1.9
  • psycopg version: 3.1.20

Additional Context:

This issue is particularly relevant in CI/CD workflows where the goal is to check for pending migrations without applying them. The current behavior prevents running makeviewmigrations --check --dry-run unless the database has already been migrated, which is counterproductive.

Would it be possible for django_db_views to modify the auto-generated migrations to account for cases where the django_content_type table doesn't exist, or offer a way to handle these queries differently in an unmigrated database?

@gabo-magnet
Copy link
Author

Additional Notes:

It’s also worth mentioning that running the following commands does not trigger the error:

  • python manage.py makemigrations --check --dry-run
  • python manage.py makemigrations

Both of these commands work fine, even in an unmigrated database. The error only occurs when using python manage.py makeviewmigrations or python manage.py makeviewmigrations --check --dry-run, which rely on the auto-generated migration views involving ContentType.

This distinction may help isolate the issue to the makeviewmigrations management command.

@BezBartek
Copy link
Owner

@gabo-magnet
Thank you for report, I will look into that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants