Automated answer in django's makemigrations - python

I want to automate the python manage.py makemigrations as in if a user encounters Did you rename game.last to game.las (a CharField)? [y/N] then the input will always be y but if the user encounters You are trying to add a non-nullable field 'las' to game without a default then it will automatically and continuously enter 1.
I tried yes | python manage.py makemigrations as researched however this will just throw an infinite loop of Please select a valid option if the default input is asked
My desire is the automation between 1 and y value as mentioned on my first paragraph or just throw an error if I input a wrong option on the default input

First, run manage.py makemigrations locally. It makes a script to modify the database schema and that is part of development and places it in the project/migrations directory. Build the container such that the generated migrations are included in your Docker container (they should be automatically as they are part of the Django project source tree), and run manage.py migrate --noinput on start-up of the container. It will automatically apply any migrations that haven't been applied. Your migrations build up over time but you can squash them if you REALLY need to, I would recommend against it except rare circumstances.
This way, you will keep your development and production database schema in sync, and won't run into strange bugs because you generated new migrations on production that didn't exist in your development environment.
I would recommend purposefully designing your migrations so that they don't require any input on manage.py migrate. That is not always possible, for instance, stale models will sometimes require input and just be left there unless manually deleted.
Since all of the Django source is available to you, it's trivial to make a version of the migrate command that assumes y and place it as a management command. Then run that management command instead of migrate, done.
I would show an example of this but it is specific to the version of Django you are running.

I actually solved the problem via timeouts like timeout 30 yes | python manage.py makemigrations so if in case an infinite loop via wrong option selection on non-nullable field input returns. It will automatically exit after 30 seconds. Giving me an alternative somehow to proceed my CI/CD without pushing my migrations

Related

Why does Django not see migrations?

I am trying to change some field names of Django models, but for some reasons Django does not want to see my migrations. I made sure the following things are properly set up:
myApp.apps.MyAppConfig is added to INSTALLED_APPS in settings.py
A migration folder with an empty __init__.py is present in my app folder
In myApp folder, I also have an empty __init__.py
The whole procedure works just fine locally with a SQLite database and I can change field names and run python manage.py makemigrations and python manage.py migrate to migrate the database. However in production where I use Docker Compose for orchestration and Postgres as database only the first migration works fine. Afterwards when I change any model field name and try to run docker-compose exec projectname django-admin makemigrations or docker-compose exec projectname python manage.py makemigrations or add the app name behind these commands nothing helps.
Then Postgres can't handle the request, because it doesn't know the new field name:
2022-03-11 14:40:22.136 UTC [81] ERROR: column model_name.new_field_name does not exist at character 357
What am I missing here? How can I get Django to migrate?
I had the same issues when using version control to submit changes to another environment.
What probably happens is that django believes it already made the migration, because of the information that is being passed along when you push those changes. What you need to do is to correct that behavior manually deleting those migrations or, if you don't need to keep information yet, force the migration from the beginning.
You may want to read the docs for future use, and I used the answers in this questions to solve the same issue.
At the end I was able to solve this issue by adding a Docker volume for the migrations folder. I believe a lot of times people put their entire code in a persistent volume, which would've also prevented this issue. However at least everything that needs to be persistent (obviously) needs a persistent volume.

Applying Django migrations in a non-interactive environment

I've renamed some models in Django and created the migrations using python manage.py makemigrations.
When using python manage.py migrate, I get prompted with the following message
Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you're unsure, answer 'no'.
Type 'yes' to continue, or 'no' to cancel:
On my local machine, I can simply type 'yes'. However,
my application is deployed on Heroku and I have configured migrations to run automatically when the application is built. I achieve this using a post_compile file that looks like this:
# Run Django migrations
./manage.py migrate
# Compress static assets
./manage.py compress
Will the migration simply fail to complete as a consequence of not being in an interactive shell (and therefore not being able to answer 'yes' to this question)? If so, how can this problem be avoided?
You can use the --noinput command line argument of migrate command:
./manage.py migrate --noinput
This would suppress the prompt, but will not delete stale content types (ie. it works as if you answered No at the prompt). See Django ticket #25036 .
Another alternative would be to use the Unix command yes (I am not sure if it is enabled on Heroku by default though):
yes "yes" | ./manage.py migrate

Column does not exist in django 1.6.5

I have an application in Django 1.6.5. I have a model where I removed one field, I added another field, and the third upgraded. And when we now turn to the model in the admin panel, I get the message:
ProgrammingError at /admin/app/subscription/
column app_subscription.enabled does not exist
The command python manage.py syncdb does not work.
Django (hopefully) doesn't modify your database schema if you don't explicitely ask for it. The syncdb command works perfectly, but (as documented) it will only create tables that don't yet exists (and are not marked as being managed externally in your models).
So you have mostly three options here:
manually drop your table and re-run syncdb. This mean you will loose all our data, so it's hardly a "solution"
manually alter your database schema. You won't loose your data, but you'll have to repeat the same (manual) operation everywhere your app is deployed... If it's only installed on your local workstation that might be ok, else it's not a reliable professional production-level option.
Use South (which seems to be installed since you do have a migrate command available.
Note that solution #3 imply that you do create the migration files for your app, as documented here : http://south.readthedocs.org/en/latest/tutorial/part1.html#the-first-migration
It just happened that I faced the same issue with django 1.9.x, where I added a new field in my django app which triggered the same error as you mentioned above.
I logged into the dbshell environment using
python manage.p dbshell # I know some use ./manage.py
and dropped all of my tables by running the following command within the dbshell to drop the tables
your_psql=# drop schema public cascade;
This will drop all of your tables (be careful as you may lose your data, there away to keep the data!) and you will get a message right after executing this command tells you that all dropped. Right after that run the following command to create the schema again, otherwise your server will not run:
your_psql=# create schema public;
Then just do the
python manage.py makemigrations # you might not need this, and
python manage.py migrate
And you're ready to go.
I know this answer might be very late but I hope it will help someone.
Cheers

What's the right way to handle an initial database migration in Django?

I'm in the process of preparing a Django application for its initial production release, and I have deployed development instances of it in a few different environments. One thing that I can't quite get happening as smoothly as I'd like is the initial database migration. Given a fresh installation of Django, a deployment of my application from version control, and a clean database, manage.py migrate will handle the initial creation of all tables (both Django's and my models'). That's great, but it doesn't actually create the initial migration files for my apps. This leads to a problem down the road when I need to deploy code changes that require a new database migration, because there's no basis for Django to compute the deltas.
I've tried running manage.py makemigrations as the first step in the deployment, in the hopes that it would create the migration files, but it reports that there are no changes to migrate. The only way I've found to get the baseline state that I need is to run manage.py makemigrations [appname] for each of my apps. Shouldn't makemigrations, called without a specific app name, pick up all the installed apps and create their migrations? Where am I going wrong?
You're going wrong at the very end -- yes, you do need to call manage.py makemigrations <appname> for each of your apps once. It's not automatically done for all apps.
Presumably that is because Django has no way of knowing if that is what you want to do (especially if some apps were downloaded from PyPI, etc). And a single command per app can't really be an extreme amount of work, right?

Django In-Memory SQLite3 Database

I'm trying to have a purely in-memory SQLite database in Django, and I think I have it working, except for an annoying problem:
I need to run syncdb before using the database, which isn't too much of a problem. The problem is that it needs to create a superuser (in the auth_user table, I think) which requires interactive input.
For my purposes, I don't want this -- I just want to create it in memory, and I really don't care about the password because I'm the only user. :) I just want to hard-code a password somewhere, but I have no idea how to do this programmatically.
Any ideas?
Any inputs or prompts of django-admin.py may be suppressed using the --noinput option, such as
./manage.py syncdb --noinput
This will skip the super user creation on the initial syncdb run and thus requires you to create one either using fixtures or an custom method as receiver of the post_syncdb signal.
See django-admin.py and manage.py in the Django docs:
--noinput
Use the --noinput option to suppress
all user prompting, such as "Are you
sure?" confirmation messages. This is
useful if django-admin.py is being
executed as an unattended, automated
script.
Disconnect django.contrib.auth.management.create_superuser from the post_syncdb signal, and instead connect your own function that creates and saves a new superuser User with the desired password.
You will want to use fixtures:
https://docs.djangoproject.com/en/1.3/howto/initial-data/

Categories