197π
Every migration is inside a transaction. In PostgreSQL you must not update the table and then alter the table schema in one transaction.
You need to split the data migration and the schema migration. First create the data migration with this code:
for sender in orm['fooapp.EmailSender'].objects.filter(footer=None):
sender.footer=''
sender.save()
Then create the schema migration:
manage.py schemamigration fooapp --auto
Now you have two transactions and the migration in two steps should work.
204π
Another reason for this maybe because you try to set a column to NOT NULL
when it actually already has NULL
values.
- [Django]-Name '_' is not defined
- [Django]-Django admin default filter
- [Django]-Django urlsafe base64 decoding with decryption
37π
At the operations I put SET CONSTRAINTS:
operations = [
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE;'),
migrations.RunPython(migration_func),
migrations.RunSQL('SET CONSTRAINTS ALL DEFERRED;'),
]
- [Django]-Combining Django F, Value and a dict to annotate a queryset
- [Django]-Django REST Framework: how to substitute null with empty string?
- [Django]-How to print BASE_DIR from settings.py from django app in terminal?
27π
If you are adding a non-nullable field, you need to do it in two migrations:
AddField
andRunPython
to populate itAlterField
to change the field to be non-nullable
Explanation
On PostgreSQL and SQLite, this problem can occur if you have a sufficiently complex RunPython
command combined with schema alterations in the same migration. For example, if you are adding a non-nullable field, the typical migration steps for this is:
AddField
to add the field as nullableRunRython
to populate itAlterField
to change the field to be non-nullable
On SQLite and Postgres, this can cause problems because the whole thing is being done in one transaction.
The Django docs have a specific warning about this:
On databases that do support DDL transactions (SQLite and PostgreSQL), RunPython operations do not have any transactions automatically added besides the transactions created for each migration. Thus, on PostgreSQL, for example, you should avoid combining schema changes and RunPython operations in the same migration or you may hit errors like OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events.
If this is the case, the solution is to separate your migration into multiple migrations. In general, the way to split is to have a first migration containing the steps up through the run_python command and the second migration containing all the ones after it. Thus, in the case described above, the pattern would be the AddField
and RunPython
in one migration, and the AlterField
in a second.
- [Django]-Difference between User.objects.create_user() vs User.objects.create() vs User().save() in django
- [Django]-How to set the timezone in Django
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
11π
Have just hit this problem. You can also use db.start_transaction() and db.commit_transaction() in the schema migration to separate data changes from schema changes. Probably not so clean as to have a separate data migration but in my case I would need schema, data, and then another schema migration so I decided to do it all at once.
- [Django]-Django: Safely Remove Old Migrations?
- [Django]-Uninstall Django completely
- [Django]-Querying django migrations table
3π
In my case Iβve got
- AddField
- RunPython
- RemoveField
Then I just moved the last RemoveFied to the new migration file, that fixed the problem
- [Django]-Django import error β No module named core.management
- [Django]-How can I enable CORS on Django REST Framework
- [Django]-How to pass multiple values for a single URL parameter?
3π
@Zags answer is correct, this error usually comes when you mix schema alteration and data manipulation in the same migration, which correspond to a unique transaction by default.
Another solution to solve that issue is to manually set atomic = False
to the Migration class. As a result, no transaction is created to run operations, each one is run sequentially and immediatly applied to the database.
class Migration(migrations.Migration):
atomic = False
dependencies = [
('application', '00XX_previous_migration'),
]
operations = [
migrations.AddField(
model_name='foo',
name='bar',
field=models.CharField(max_length=255),
),
RunPython(migrate_data, reverse_code=reverse_migrate_data, atomic=True),
migrations.RemoveField(
model_name='foo',
name='baz',
),
]
Tip: If the RunPython operation perform multiple save(), you can call it with atomic=True
to create a transaction for the whole operation.
- [Django]-What is the purpose of adding to INSTALLED_APPS in Django?
- [Django]-How to make two django projects share the same database
- [Django]-Django. A good tutorial for Class Based Views
2π
You are altering the column schema. That footer column can no longer contain a blank value. There are most likely blank values already stored in the DB for that column. Django is going to update those blank rows in your DB from blank to the now default value with the migrate command. Django tries to update the rows where footer column has a blank value and change the schema at the same time it seems (Iβm not sure).
The problem is you canβt alter the same column schema you are trying to update the values for at the same time.
One solution would be to delete the migrations file updating the schema. Then, run a script to update all those values to your default value. Then re-run the migration to update the schema. This way, the update is already done. Django migration is only altering the schema.
- [Django]-How do I filter ForeignKey choices in a Django ModelForm?
- [Django]-Where is a good place to work on accounts/profile in Django with the Django registration app?
- [Django]-Django template includes slow?
0π
step 1)the solution is to remove the latest migration from the migration folder and remove the latest added fields in models.
step 2)then again makemigration and migrate
step 3)At the last add the field again that has been removed in the first step
step 4)then again makemigration and migrate
Problem solved
- [Django]-Has Django served an excess of 100k daily visits?
- [Django]-How does django handle multiple memcached servers?
- [Django]-What does on_delete do on Django models?
0π
The likely cause of this is rooted in your model having check constraints on it via the Meta.constraints
option. Check constraints (in Postgres) are implemented as triggers that execute at the end of a transaction. By default, a Django migration file encloses all migrations operations from a file in a single transaction. This means that other ALTER TABLE
operations may happen before your triggers fire, a situation that Postgres canβt handle.
In order to get around this issue, you can do like another answer suggested:
operations = [
migrations.RemoveField(...). # Do your normal table operations
migrations.RunPython(migration_func),
# Evaluate the check constraints
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE;'),
migrations.RemoveField(...). # Run the rest of your table operations
]
Running 'SET CONSTRAINTS ALL IMMEDIATE;'
after the data migration ensures that all of those check constraints that normally wait until the end of the transaction will fire, meaning there are no more pending trigger events before the next ALTER TABLE
statements.
FYI β This setting is effective for only the Django migration runner in that transaction. It wonβt affect other database sessions or any subsequent migration files.
Unlike the other answer linked, Iβd avoid running an additional migrations.RunSQL('SET CONSTRAINTS ALL DEFERRED;')
, otherwise you may alter the behavior of other triggers in subsequent steps that should run immediately (i.e. application triggers that track history, etc, that arenβt check constraints).
Just wanted to add some more clarity here on exactly why this is happening since this is an older question with many different answers.
- [Django]-Django.db.utils.ProgrammingError: relation "bot_trade" does not exist
- [Django]-Itertools.groupby in a django template
- [Django]-How to obtain and/or save the queryset criteria to the DB?