How to squash squashed migration in django? - django

For example, I have 50 migrations and i have squashed all the migrations to 0001_initial.py and after reaching again 50 migrations. How do i squash the migrations?

Before you can squash your new migrations, you need to transition your squashed migrations into normal migrations as outlined in the documentation (at the end of the section):
You must then transition the squashed migration to a normal migration
by:
Deleting all the migration files it replaces.
Updating all migrations that depend on the deleted migrations to depend on the squashed migration instead.
Removing the replaces attribute in the Migration
class of the squashed migration (this is how Django tells that it is a
squashed migration).
Once you have removed the original migrations that were squashed, along with all references, the squashed migrations become the "normal" migrations, and you will be able to squash these again.

python manage.py squashmigrations <appname> <squashfrom> <squashto>
python manage.py help squashmigrations

If you have already squashed once, your squash file contains this code.
replaces = [('model_name', '0001_auto...
After commenting the code above.
# replaces = [('model_name', '0001_auto...
you can squash again.
python manage.py squashmigrations app_name 000x

Related

django migrations does not update database

I have django app already online and running. I created new model and if I do the makemigrations, it is working fine, but if I want to migrate it, then I receive Running migrations:No migrations to apply. Even though that I made a change. The change is also in the migration file. I am using postgresql with it. I tried to delete the migration file and create it once more, but it did not help. Any idea what might be wrong?
Looks like some migrations are marked as applied incorrectly in the database. This can be solved by using the --fake flag [Django docs] to mark an appropriate migration as applied / some migrations as unapplied.
Suppose that your app is named myapp and the migration 0004 is applied properly to the database (you are trying to apply 0005 or further which doesn't work) then you will run the following command:
python manage.py migrate myapp 0004 --fake
Note: myapp and 0004 is an example, do this according to your apps name and which migrations are applied.
Edit: It appears that you have deleted the migrations. But thankfully have some version control in place. Best would be to get the migration files back from the version control. If for some reason you are unable to do that, revert the models to how they were before their changes and make sure no migration files exist for now. Next generate the migration files by running makemigrations (check that they are as expected and your database state corresponds to these generated files). Next run the following two commands:
python manage.py migrate <appname> zero --fake
python manage.py migrate <appname> --fake
The first one will mark all migrations as unapplied for the app. The second one will mark all the migrations as applied. Next you will add the changes you wanted to make back to the models and migrate again.

Deleted migration files- how to makemigrations without losing data

I changed a field on a model class (which has no classes point to it, only one foreign key pointing out of it). Somehow, this stuffed up my migrations and it keeps saying "django.db.migrations.graph.NodeNotFoundError:" looking for migration files that do not exist.
I accidentally deleted several files in my 'migrations' folder.
My database contains a lot of data, and I do not want to break it.
Will I lose any data if I:
Remove the table that caused the problem in the first place (psql, \d, DROP TABLE tablename)
delete all my migration files
Re run the migration from the start?
./manage.py makemigrations
./manage.py migrate
Can anyone recommend another way of fixing this?
Here is the traceback:
http://dpaste.com/0Y1YDXS
Aren't you using git so that you can get your migration files back? If not, install and use it, starting now
I would suggest:
make a backup/dump of your database first, in case something goes wrong
Delete all migrations
Empty migration table in psql
call makemigrations
call migrate --fake-initial
Empty the django_migrations table:
delete from django_migrations;
Remove all the files in migrations folders in each and every app of your project.
Reset the migrations for the "built-in" apps:
python manage.py migrate --fake
Create initial migrations for each and every app:
python manage.py makemigrations your_app_name
Final step is to create fake initial migrations:
python manage.py migrate --fake-initial
See here https://micropyramid.com/blog/how-to-create-initial-django-migrations-for-existing-schema/

Django 1.8 Squashing migrations

I have some questions on Squashing in Django 1.8. I've squashed a few migration files into one but not quite sure how to do the 2 actions as specified in the djangoprojects docs.
After this has been done, you must then transition the squashed migration to a normal initial migration, by:
-Deleting all the migration files it replaces
-Removing the replaces argument in the Migration class of the squashed migration (this is how Django tells that it is a squashed migration)
Do I just delete the migration files in the migration file using normal rm command?
Do I just vim the migration file "0001_squashed_xxx" and remove the part "replaces = []"?
Also, after I run the squashed migration, the migration (original is 0010) became 0001 automatically. Is this the expected behavior?
Any help would be great. Thanks!
Do I just delete the migration files in the migration file using normal rm command?
Do I just vim the migration file "0001_squashed_xxx" and remove the part "replaces = []"?
Yes and yes, but only AFTER you've run the squashed migrations on all your production sites.
Also, you should ensure that none of your other migrations depend on the migrations you're about to delete. If they do, you should change those dependencies to point at the corresponding squashed migrations instead.
Also, after I run the squashed migration, the migration (original is 0010) became 0001 automatically. Is this the expected behavior?
This is because squashed migrations are given the name <start_migration>_squashed_<end_migration>. So if you squashed from 0001_initial to 0010_blah, the squashed migration will have the name 0001_initial_squashed_0010_blah and thus its code will start with 0001. But the numbering doesn't really mean anything, it's just there so that your migrations are nicely ordered when listed in a directory.

How to delete django migrations after squashing them?

Django documentation says we could delete migrations after squashing them:
You should commit this migration but leave the old ones in place; the
new migration will be used for new installs. Once you are sure all
instances of the code base have applied the migrations you squashed,
you can delete them.
Here, does deleting means deleting only the migration files, or the entries in the django_migrations table as well?
Here is some background: I have only the development machine, so just one code base. After squashing some of the migrations that I had already applied, I deleted the files and the database entries. Tested if this is OK by making migrations, it did not find anything. So, everything looked good. Next day, I had to change something, and made migration. When I tried to migrate, it tried to apply the squashed migration too (which was applied part by part before being squashed). So, I had to go back and recreate the entries in the django_migrations table. So, it seems like I had to keep the database entries. I am trying to make sure before I mess up anything again, and understand why it looked fine first, and then tried to apply the squashed migration.
Squashed migrations are never marked as applied, which will be fixed in 1.8.3 (see #24628).
The steps to remove the old migrations are:
Make sure all replaced migrations are applied (or none of them).
Remove the old migration files, remove the replaces attribute from the squashed migrations.
(Workaround) Run ./manage.py migrate <app_label> <squashed_migration> --fake.
The last step won't be necessary when 1.8.3 arrives.
Converting squashed migrations has gotten easier since the question was posted. I posted a small sample project that shows how to squash migrations with circular dependencies, and it also shows how to convert the squashed migration into a regular migration after all the installations have migrated past the squash point.
As the Django documentation says:
You must then transition the squashed migration to a normal migration by:
Deleting all the migration files it replaces.
Updating all migrations that depend on the deleted migrations to depend on the squashed migration instead.
Removing the replaces attribute in the Migration class of the squashed migration (this is how Django tells that it is a squashed migration).
I'm no expert by any means, but I just squashed my migrations, and ended up doing the following:
Ran this query to removed the old migrations (squashed)
DELETE FROM south_migrationhistory;
Run this management command to remove the ghosted migrations
./manage.py migrate --fake --delete-ghost-migrations
Django 1.7 also has squashmigrations

Django South - table already exists

I am trying to get started with South. I had an existing database and I added South (syncdb, schemamigration --initial).
Then, I updated models.py to add a field and ran ./manage.py schemamigration myapp --auto. It seemed to find the field and said I could apply this with ./manage.py migrate myapp. But, doing that gave the error:
django.db.utils.DatabaseError: table "myapp_tablename" already exists
tablename is the first table listed in models.py.
I am running Django 1.2, South 0.7
since you already have the tables created in the database, you just need to run the initial migration as fake
./manage.py migrate myapp --fake
make sure that the schema of models is same as schema of tables in database.
Although the table "myapp_tablename" already exists error stop raising
after I did ./manage.py migrate myapp --fake, the DatabaseError shows
no such column: myapp_mymodel.added_field.
Got exactly the same problem!
1.Firstly check the migration number which is causing this. Lets assume it is: 0010.
2.You need to:
./manage.py schemamigration myapp --add-field MyModel.added_field
./manage.py migrate myapp
if there is more than one field missing you have to repeat it for each field.
3.Now you land with a bunch of new migrations so remove their files from myapp/migrations (0011 and further if you needed to add multiple fields).
4.Run this:
./manage.py migrate myapp 0010
Now try ./manage.py migrate myapp
If it doesn't fail you're ready. Just doublecheck if any field's aren't missing.
EDIT:
This problem can also occur when you have a production database for which you install South and the first, initial migration created in other enviorment duplicates what you already have in your db. The solution is much easier here:
Fake the first migration:
./manage migrate myapp 0001 --fake
Roll with the rest of migrations:
./manage migrate myapp
When I ran into this error, it had a different cause.
In my case South had somehow left in my DB a temporary empty table, which is used in _remake_table(). Probably I had aborted a migration in a way I shouldn't have. In any case, each subsequent new migration, when it called _remake_table(), was throwing the error sqlite3.pypysqlite2.dbapi2.OperationalError: table "_south_new_myapp_mymodel" already exists, because it did already exist and wasn't supposed to be there.
The _south_new bit looked odd to me, so I browsed my DB, saw the table _south_new_myapp_mymodel, scratched my head, looked at South's source, decided it was junk, dropped the table, and all was well.
If you have problems with your models not matching your database, like #pielgrzym, and you want to automatically migrate the database to match the latest models.py file (and erase any data that won't be recreated by fixtures during migrate):
manage.py schemamigration myapp --initial
manage.py migrate myapp --fake
manage.py migrate myapp zero
manage.py migrate myapp
This will only delete and recreate database tables that exist in your latest models.py file, so you may have garbage tables in your database from previous syncdbs or migrates. To get rid of those, precede all these migrations with:
manage.py sqlclear myapp | manage.py sqlshell
And if that still leaves some CRUFT lying around in your database then you'll have to do an inspectdb and create the models.py file from that (for the tables and app that you want to clear) before doing the sqlclear and then restore your original models.py before creating the --initial migration and migrating to it. All this to avoid messing around with the particular flavor of SQL that your database needs.
Perform these steps in order may help you:
1) python manage.py schemamigration apps.appname --initial
Above step creates migration folder as default.
2) python manage.py migrate apps.appname --fake
generates a fake migration.
3) python manage.py schemamigration apps.appname --auto
Then you can add fields as you wish and perform the above command.
4) python manage.py migrate apps.appname
If you have an existing database and app you can use the south conversion command
./manage.py convert_to_south myapp
This has to be applied before you do any changes to what is already in the database.
The convert_to_south command only works entirely on the first machine you run it on. Once you’ve committed the initial migrations it made into your VCS, you’ll have to run ./manage.py migrate myapp 0001 --fake on every machine that has a copy of the codebase (make sure they were up-to-date with models and schema first).
ref: http://south.readthedocs.org/en/latest/convertinganapp.html
As temporary solution, you can comment the Table creation in the migration script.
class Migration(migrations.Migration):
dependencies = [
(...)
]
operations = [
#migrations.CreateModel(
# name='TABLE',
# fields=[
# ....
# ....
# ],
#),
....
....
Or
If the existing table contains no rows (empty), then consider deleting the table like below. (This fix is recommended only if the table contains no rows). Also make sure this operation before the createModel operation.
class Migration(migrations.Migration):
dependencies = [
(...),
]
operations = [
migrations.RunSQL("DROP TABLE myapp_tablename;")
]
One more solution(maybe a temporary solution).
$ python manage.py sqlmigrate APP_NAME MIGRATION_NAME
eg.,.
$ python manage.py sqlmigrate users 0029_auto_20170310_1117
This will list all the migrations in raw sql queries. You can pick the queries which you want to run avoiding the part which creates the existing table