Skip to content

Instantly share code, notes, and snippets.

@kezabelle
Last active March 1, 2018 11:59
Show Gist options
  • Save kezabelle/15f9f9c6f92be7ae3142ec6f5f1de960 to your computer and use it in GitHub Desktop.
Save kezabelle/15f9f9c6f92be7ae3142ec6f5f1de960 to your computer and use it in GitHub Desktop.
When `makemigrations` happens, `B` won't include the `a` FK so subsequent data migrations won't be able to query by `a`
# Generated by Django 2.1.dev20180228190652 on 2018-03-01 11:08
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='B',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'db_table': 'test_b',
'managed': False,
},
),
migrations.CreateModel(
name='A',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'db_table': 'test_a',
},
),
migrations.CreateModel(
name='C',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('a', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='whee.A')),
],
options={
'db_table': 'test_c',
},
),
]
# Generated by Django 2.1.dev20180228190652 on 2018-03-01 11:51
from django.db import migrations
def forwards(apps, schema_editor):
B = apps.get_model('whee', 'B')
B.objects.filter(a=1) # if this doesn't crash, yay, B has the field!
def backwards(apps, schema_editor):
return
class Migration(migrations.Migration):
dependencies = [
('whee', '0001_initial'),
]
operations = [
migrations.RunPython(forwards, backwards),
]
from django.db import models
class A(models.Model):
class Meta:
#managed = False
db_table = "test_a"
class B(models.Model):
a = models.ForeignKey(A, related_name="+", on_delete=models.CASCADE)
class Meta:
managed = False
db_table = "test_b"
class C(models.Model):
a = models.ForeignKey(A, related_name="+", on_delete=models.CASCADE)
class Meta:
db_table = "test_c"
@kezabelle
Copy link
Author

Commenting out the lines:

            # Don't add operations which modify the database for unmanaged models
            if not model_opts.managed:
                continue

from https://github.com/django/django/blob/75527c0f8360ae3555fcf67ce19b4cb910b69b9d/django/db/migrations/autodetector.py#L570-L572

puts the FK into B, but does so differently depending on whether A is managed = True or managed = False

  • if A.Meta.managed = True then there's a CreateModel for B (containing just the id field) followed by an AddField adding a to B.
  • if A.Meta.managed = False then there's just a CreateModel for B which includes both the id and the a fields at once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment