Django ManyToMany table missing even though migrations are applied (Docker + Postgres)

Problem

I am working on a Django project using a PostgreSQL container in Docker. I added a ManyToManyField to one of my models. I keep migrations in .gitignore because my local and production databases are different, so I only pushed the model changes to GitHub. On my server, I pulled the code and ran docker compose up, which automatically runs makemigrations and migrate. There were no errors or warnings, and the generated migration file correctly includes the ManyToMany Field. Django shows the migration as applied. However, when I try to access the ManyToMany relation at runtime, I get a database error saying the join table does not exist.

Environment

  • Django
  • PostgreSQL
  • Docker

Model

class Contact(models.Model):
    ...

class CallCampaign(models.Model): 
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) 
    error = models.TextField(blank=True, null=True) 
    company = models.ForeignKey(Company, on_delete=models.CASCADE) 
    selected_contacts = models.ManyToManyField('Contact', blank=True) 
    ...

Migration

The migration file includes the ManyToManyField:

migrations.CreateModel( 
    name='CallCampaign', 
    fields=[ 
        ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 
        ('error', models.TextField(blank=True, null=True))
        ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='companies.company')), 
        ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 
        ('selected_contacts', models.ManyToManyField(blank=True, to='contacts.contact')), 
    ], 
), 

The migration is marked as applied in the database.

What happens at runtime

>>> from contacts.models import CallCampaign 
>>> c = CallCampaign.objects.first() 
>>> c.selected_contacts 
<ManyRelatedManager object at 0x...> 
 
>>> c.selected_contacts.all() 

Error:

django.db.utils.ProgrammingError: 
relation "contacts_callcampaign_selected_contacts" does not exist 
LINE 1: ..."."created_at" FROM "contacts_contact" INNER JOIN "contacts_... 

Database tables

Existing tables:

contacts_callcampaign 
contacts_contact 
contacts_callhistory 

Missing table:

contacts_callcampaign_selected_contacts 

Migration status

The django_migrations table shows:

app     | name         | applied 
--------|--------------|-------- 
contacts| 0001_initial | 2025-12-29 16:21:00 

Commands I ran:

python manage.py makemigrations 
# No changes detected 
 
python manage.py migrate 
# No migrations to apply 

Django does not attempt to create the missing ManyToMany table.

Docker setup (simplified)

services: 
  db: 
    image: postgres:15 
    volumes: 
      - postgres_data:/var/lib/postgresql/data/ 
    healthcheck: 
      test: ["CMD-SHELL", "pg_isready -U postgres"] 
      interval: 5s 
      timeout: 5s 
      retries: 5 
 
  web: 
    build: . 
    command: > 
      sh -c " 
      python manage.py makemigrations --noinput && 
      python manage.py migrate --noinput
      " 
    depends_on: 
      db: 
        condition: service_healthy 
 
volumes: 
  postgres_data: 

The Postgres volume is persistent across restarts and rebuilds.

Questions

  1. How can a Django migration be marked as applied if the ManyToMany table was not created?
  2. Is this expected behavior in Django migrations? (i.e., no atomicity guarantee for the entire migration)
  3. How can this be prevented when using Docker with persistent databases?
  4. What can i do now?

I want to understand why this happens and what the correct way is for Django migrations and ManyToMany tables so this does not occur in the future.

Вернуться на верх