Django: How to write migrations that don't require keyboard input? - django

I'm wondering if there's a way to write migrations that won't ask me for input at the terminal. For example, while writing a migration that deletes a model, Django asks me to confirm this at the command line with a yes/no. I want to avoid these prompts because the same code will be used for automatic deployments (can't type in prompts during automatic deployment).
I'm aware there's the noinput option. I'm more interested in learning how to write migrations that don't require keyboard input, if possible. I've also noted that sometimes even when using this option, I get prompted anyway (one example that comes to mind was a migration that asked me to input default data for new columns being added to the model; noinput didn't stop Django from asking for my input anyway).

There are two situations here: makemigrations and migrate.
migrate is 100% covered by the --noinput option: unless you install a custom, third-party pre/post migrate signal hook that ignores the option, you'll get no user prompts with this option.
makemigrations is not 100% covered by the --noinput option, and while it's a nice-to-have, it's absolutely not necessary. Migrations should always be created and tested in your development environment. I've yet to see a development environment where you can't provide manual input.
1.9 will in time introduce better support for the --noinput in combination with makemigrations (at the moment, it only supports --noinput in combination with --merge).

Related

Django migrate rollback multiple migrations on failure

Django migrations has excellent behavior in terms of single migrations, where, assuming you leave atomic=True, a migration will be all-or-nothing: it will either run to completion or undo everything.
Is there a way to get this all-or-nothing behavior for multiple migrations? That is to say, is there a way to either run multiple migrations inside an enclosing transaction (which admittedly could cause other problems) or to rollback all succeeded migrations on failure?
For context, I'm looking for a single command or setting to do this so that I can include it in a deploy script. Currently, the only part of my deploy that isn't rolled back in the event of a failure are database changes. I know that this can be manually done by running python manage.py migrate APP_NAME MIGRATION_NUMBER in the event of a failure, but this requires knowledge of the last run migration on each app.
This isn't a feature in Django (at least as of 4.1). To do this yourself, your code needs to do the following:
Get a list of current apps that have migrations. This can be done by getting the intersection of apps from settings.INSTALLED_APPS and the apps in the MigrationRecorder.
Get the latest migration for each app.
Run migrations.
If migrations fail, run the rollback command for the latest migration for each app.
Here's an implementation of this as a custom management command: https://github.com/zagaran/django-migrate-or-rollback. This is done as a child-class of the migrate management command so that it exposes all of the command line options of migrate. To use this library, pip install django-migrate-or-rollback and add "django_migrate_or_rollback" to your INSTALLED_APPS in settings.py. Then you can use python manage.py migrate_or_rollback in place of the traditional migrate command.
Disclosure: I am the author of the library referenced (though I made the library based on this StackOverflow answer).

Django: python manage.py migrate --noinput

I am considering to add the command release: python manage.py migrate --no-input to my deployment, so Heroku is automatically migrating, once I push my repository. I now wonder if --no-input is a 'good' idea?
One more specific question: If migrate normally asks me 'Did you rename this field'. With --no-input, will it answer automatically yes? I couldn't find much detailed information in the official Django documentation.
We don't use the interactive flag (--no-input) in our pipeline and to the best of my knowledge it doesn't make much difference. If you inspected Django source code, you would find out that the interactive flag only falls through to the pre_migrate and post_migrate signals that are emitted prior to and post migration.
As far as I know, no internal Django app uses the interactive argument inside these signals. Some external packages perhaps could use that, but I personally have never encountered that.
As for your question:
One more specific question: If migrate normally asks me 'Did you rename this field'. With --no-input, will it answer automatically yes? I couldn't find much detailed information in the official Django documentation.
This happens in the makemigrations management command, not in migrate. You usually do (and should do) the former locally, so no need to include that in your deployment pipeline.

Deleted Migration folder (Django 1.8) by accident what are my options?

I have accidently deleted one of migrations folders and and have no backup for it.
What are my options?
DB is postgres. Right now everything is OK.(I have moved instead migration folder I have on my DEV server with SQL lite) So I am just getting red message on server that not all migrations have been applied.
But next time if i run migration i will be in trouble.
What is my way out?
Migrations are mainly for backward compatibility, and tracking/versioning of the changes to models/database. If you do not really care about historical changes, etc.. then you can just delete the migrations directory and do:
python manage.py makemigrations <app_name>
This creates the initial migrations (like starting from a clean slate) - and moving forward you can track the historical migrations moving forward. More on this can be read here
Now, when you run the migrations, you can do
python manage.py migrate <app_name> --fake-initial
to fake the initial migration.
Now might be a good time to have a version control on your application
Use version control.
You are not the first developer to delete important files, but often recovery takes less than a second - thanks to version control systems (also called revision control systems). Please stop everything else and install and use one of Git, Mercury or Subversion.
Don't use FTP
It's totally. I mean totally insecure. Always use SFTP
Don't use sqlite3 for local with other db for production
sqlite doesn't enforce strict type checking. Postgresql on the other hand is very particular about it. Additionally sqlite only has a subset of the functionality that's found on postgresql. Last but not least different RDBMS have different intricacies. If you use one locally and another in production, there is always a chance that your code will break when you deploy to live
Managing without the migration files
This is not a big loss as long as your database is in sync with your models.
If you database is not in sync with your models, you can use
./manage.py inspectdb
to recreate local models that represent the actual structure in the db. Then you do makemigrations and migrate (as explained by karthik) on the generated models.
Then replace that with your live models and do the step again.

Django migrations gives error when run separately in different machines

We are a team of developers working on Django project. We are facing issues with django migrations. if one developer makes changes in model and runs makemigrations>migrate sequence it generates some sqls in migrations directory. Now when other developer pulls the code, and run the same sequence it's putting code in bad state. We've been clearing our migrations directory locally to get rid of the issue, and sometimes clear all the data. Not sure what we're doing incorrectly. Please suggest the right way of using django migrations.
Note - All of us use separate instances of DB in local machine.
makemigrations just create files
By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.
Migrations are how Django stores changes to your models (and thus your database schema) - they’re just files on disk. You can read the migration for your new model if you like; it’s the file polls/migrations/0001_initial.py.
Under Version Control, after you push the migrations file, for example, 0001_initial.py. Other developers just pull the file then run
python manage.py sqlmigrate your_app 0001 # to see what happen
python manage.py migrate your_app 0001
More about the Version Control:
Version control
Because migrations are stored in version control, you’ll occasionally come across situations where you and another developer have both committed a migration to the same app at the same time, resulting in two migrations with the same number.
Don’t worry - the numbers are just there for developers’ reference, Django just cares that each migration has a different name. Migrations specify which other migrations they depend on - including earlier migrations in the same app - in the file, so it’s possible to detect when there’s two new migrations for the same app that aren’t ordered.
When this happens, Django will prompt you and give you some options. If it thinks it’s safe enough, it will offer to automatically linearize the two migrations for you. If not, you’ll have to go in and modify the migrations yourself - don’t worry, this isn’t difficult, and is explained more in Migration files below.

Can stale content types be automatically deleted in Django?

I'm working with a PyQt application which uses Django to deliver it's content to desktop users.
In the latest update we have stale content types stored in the database by Django and on startup of the application South's migrate or syncdb offers to delete them. Is it possible to do something with the call to migrate/syncdb that automatically deletes these?
This prompt can't be exposed to the end user for obvious reasons, so I really hope there is some way we can take car of this automatically :)
I've seen that with the South migrate you can call --noinput but that doesn't delete them, and it'd be good if we could do that as we know it'll be safe.
On unix systems there is a command yes, which will repeatedly output a string to stdout, separated by newlines. We can use this to auto-answer this prompt.
yes "yes" | python ./manage.py migrate
I use this command to automatically answer yes in my scripts when I'm doing Django migrations:
cat <(echo "yes") - | ./manage.py syncdb --migrate
Note that this only takes care of the first prompt. You can read more about the details of how this works and how to add an automatic answer to a second prompt here:
https://stackoverflow.com/a/16347534/1636882