Are there django commands that
A. Delete all tables
B. delete all data in all tables
C. Create all tables as defined in the model?
I cannot find these right now!
And by commands i mean those little things that are like
runserver
etc
A. Delete all tables
manage.py sqlclear will print the sql statement to drop all tables
B. delete all data in all tables
manage.py flush returns the database to the state it was in immediately after syncdb was executed
C. Create all tables as defined in the model?
manage.py syncdb Creates the database tables for all apps in INSTALLED_APPS whose tables have not already been created.
See this page for a reference of all commands: https://docs.djangoproject.com/en/dev/ref/django-admin/
But you should definitely look into using south as someone already mentioned. It's the best way to manage your database.
N.B: syncdb is deprecated in favour of migrate, since Django 1.7.
If you have the client libraries installed for your database, you can run this:
python manage.py sqlflush | python manage.py dbshell
This doesn't drop the tables, but truncates them.
There isn't a command that does the it all in one go, but this "one liner" will drop all the tables and then re-create them. It would only work if you were running on a system that provides these utilities at the shell.
echo 'from django.conf import settings; print settings.INSTALLED_APPS; quit();' | python manage.py shell --plain 2>&1 | tail -n1 | sed -r "s|^.*\((.*)\).*$|\1|; s|[',]| |g; s|django\.contrib\.||g" | xargs python manage.py sqlclear | python manage.py dbshell && python manage.py syncdb
Neither manage.py sqlclear nor manage.py reset is capable of dropping all tables at once, both require an appname parameter.
You should take a look at Django Extensions, it gives you access to manage.py reset_db as well as many other useful management commands.
I recommend using django-south. It allows you to sync your models to your database not just when you add a field, but also when you delete a field/model. I really find it to be an essential component of building a Django site. Once installed, you could run a command like:
./manage.py migrate app zero
You can learn more here: http://south.aeracode.org/docs/about.html
And a simpler oneliner to drop all the tables for django 1.5+:
python2 manage.py sqlflush | sed 's/TRUNCATE/DROP TABLE/g'| python2 manage.py dbshell
I was able todrop my tables. Run
python manage.py sqlclear appname
Take note of the commands given. Then run
python manage.py dbshell
Add the commands given in the first step. line by line. When you are done, type '.exit' (for SQlite3). Resync your DB and you should be good to go. To be sure, check the tables with:
python manage.py shell
>>> from yourapp import yourclasses
>>> yourviews.objects.all()
it should return a []. I hope this helps.
A implies B, right?
For A, see How to drop all tables from the database with manage.py CLI in Django?
For C,
python manage.py syncdb
Ofcourse for smart data migration I go with what #bento mentioned: django-south
Related
I'm using django 1.9.6. I recently deleted my migrations and ran migrate --run-syncdb and makemigrations my_app. Today I added a new field to one of my models:
models.py:
value = models.PositiveSmallIntegerField(null=True)
I tried to migrate the changes, but makemigrations doesn't detect the change. It's just the development version, so I can resync (I don't have to preserve the data), but running --run-syncdb again doesn't detect it either.
Why isn't this migrating?
Delete every past migration files and __pycache__ files except __init__
then:
python manage.py makemigrations yourApp
After that make sure that the db is the same as the code in model.py (remove new changes) and run next line:
python manage.py migrate --fake-initial
Now add all your changes in the model.py and run next lines:
python manage.py makemigrations
python manage.py migrate
Best Regards,
Kristian
I had the same issue. I realised I had a property defined on the model with the same name as a field I was trying to add on the model. Ensure the model doesn't have a model property/method with the same name as the field you are trying to add.
You should not delete migrations, you should squash them. If you simply deleted the files you likely messed things up, the easiest way to recover is re-sync your code to get the files back. A more complex route is to delete all the records from the django_migrations table and re-init the migrations from scratch but there is more steps/issues than I can really get into and I don't recommend it.
The reason makemigrations is not detecting the change is likely because there is no migrations folder in that app. If you run python manage.py makemigrations your_app --initial it might detect and generate the migrations or it might freak out because of the difference in your files and the django_migrations table.
The --run-syncdb command is great when you don't care about the data, usually before you actually deploy but once you start using migrations you should not use the --run-syncdb command anymore. For instance, during initial development here is the code I run every model change instead of dealing with migrations:
dropdb mydb && createdb mydb && python manage.py migrate --run-syncdb && python manage.py loaddata initial
I store all the initial data in a fixtures file and the command wipes out the entire database, the --run-syncdb rebuilds the schema, and the initial data is loaded while skipping actual migration files.
So, if you don't care about any of your data or can easily move it to a fixture than you can drop and re-create the DB. You are then free to delete all migration folders and you can use the command above until you go live and need to move to using migrations.
*** UPDATE FOR DJANGO 1.11 *** STILL USING ON 3.2.5 ***
I started using Django 1.11 and noticed the test framework can fail if you have dependencies on framework models and don't actually have migrations. This is the new command i'm using to wipe everything out and start over while still developing.
set -e
dropdb yourdb
createdb yourdb
find . -name "migrations" -type d -prune -exec rm -rf {} \;
python manage.py makemigrations name every app you use seperated by space
python manage.py migrate
python manage.py loaddata initial
I put this in a builddb.sh at the root of my project (next to manage.py) so I can just run ./builddb.sh. Be sure to delete it on deploy so there is no accidents!
Try creating a migrations folder that contains an empty __init__.py file inside your app folder if there is no migrations folder already. And make migrations.
In my case, I created a new project and created an app. The python manage.py makemigrations returned no change detected although I had added a handful of models.
Found out that you need to manually add the name of your app in the INSTALLED_APPS list inside your settings.py file. Unless you do that, no change in the migration of that app can be detected.
If you're deleting a model, and expecting the changes to be picked up in migrations, ensure that the model doesn't have a *.pyc still lying around.
Another case is abstract classes. Make sure that your model’s metaclass does not have the abstract = True property.
How would I rerun a data migration on Django 1.8+? If relevant, my migration is numbered 0011_my_data_migration.py and is the latest migration.
Fake back to the migration before the one you want to rerun.
./manage.py migrate --fake yourapp 0010_my_previous_data_migration
Then rerun the migration.
./manage.py migrate yourapp 0011_my_data_migration
Then you can fake back to the most recent migration that you have run. In your case, you said that 0011 was the latest, so you can skip this stage.
./manage.py migrate --fake yourapp 0014_my_latest_data_migration
Note that depending on the state of your database and the contents of the migrations, rerunning a migration like this might cause errors. Note the warning in the docs about the --fake option:
This is intended for advanced users to manipulate the current migration state directly if they’re manually applying changes; be warned that using --fake runs the risk of putting the migration state table into a state where manual recovery will be needed to make migrations run correctly.
Alasdair's answer gives a disclaimer about this, but faking a migration back to the previous one is only safe if your migration is idempotent, which means you can run it multiple times without side effects like duplicate data. Most people don't write their migrations this way, but it's good practice.
You have two options to make this process safe:
Make your data migrations idempotent. This means that any created data is either reused (like with the Model.objects.get_or_create() method) or deleted and recreated. Reused is the better option, as deleting and recreating will change database indexes and sequences.
Make reverse data migrations. You can do this by passing 2 functions to migrations.RunPython(). For example, if you have migrations.RunPython(add_countries), you would change that to migrations.RunPython(add_countries, remove_countries) and delete any relevant countries in the second function.
If you choose option #2 then you would run:
./manage.py migrate yourapp 0010_my_previous_data_migration
./manage.py migrate yourapp 0011_my_data_migration
If you wanted to make that a one liner so that you can use it over and over:
./manage.py migrate yourapp 0010_my_previous_data_migration && ./manage.py migrate yourapp 0011_my_data_migration
Based on the accepted answer, here's a script for reapplying a given migration.
#! /bin/bash
# This script re-applies a given migration.
app_name="$1"
migration_index="$2"
prev_migration_index="$(echo "$migration_index" | sed 's/^0*//' | awk '{ print $1 - 1 }' | xargs printf "%04d")"
last_migration_index="$(django-admin showmigrations --plan | grep -oP "\.\K\d{4}" | sort | tail -n 1)"
# fake-migrate to the migration prior to the one we want to reapply
django-admin migrate --fake "$app_name" "$prev_migration_index"
# reapply the migration
django-admin migrate "$app_name" "$migration_index"
# fake-migrate to the last migration
django-admin migrate --fake "$app_name" "$last_migration_index"
Usage:
$ bash reapply_migration.sh <app_name> <migration_to_reapply_index>
Using django 1.7.7 I want to use django's migration to add or remove a field.
so I modified model.py and ran
python manage.py makemigrations myproj
Migrations for 'myproj':
0001_initial.py:
- Create model Interp
- Create model InterpVersion
python manage.py migrate myproj
Operations to perform:
Apply all migrations: myproj
Running migrations:
Applying myproj.0001_initial... FAKED
python manage.py runserver
Then checked the admin page, it is not updated.
Then I tried removing the migration folder and tried again; the migrate command says there are no migrations to apply.
How can I do the migration?
Note: I want to use the new technique using django's migration not the old south approach.
Make sure that the migrations/ folder contains a __init__.py file
Lost half an hour over that.
Deleting the migration directory is never a good idea, because Django then loses track of which migration has been applied and which not (and once an app is deployed somewhere it can become quite difficult to get things back in sync).
Disclaimer: whenever things like that occur it is best to backup the database if it contains anything valuable. If in early development it is not necessary, but once things on the backend get out of sync there is a chance of things getting worse. :-)
To recover, you could try resetting your models to match exactly what they were before you have added/removed the fields. Then you can run
$ python manage.py makemigrations myproj
which will lead to an initial migration (0001_initial...). Then you can tell Django to fake that migration, which means to tell it to set its internal counter to this 0001_initial:
With Django 1.7:
$ python manage.py migrate myproj
With Django >= 1.8:
$ python manage.py migrate myproj --fake-initial
Now, try to change your model and run makemigrations again. It should now create a 0002_foobar migration that you could run as expected.
In my case, the migrations were not being reflected in mysql database. I manually removed the row of 'myapp'(in your case 'myproj') from the table 'django_migrations' in mysql database and ran the same commands again for migration.
Most of the above solutions would help in the issue, however, I wanted to point out another possible (albeit rare) possibility that the allow_migrate method of database router may be returning False when it should have returned None.
Django has a setting DATABASE_ROUTERS which will be used to determine which database to use when performing a database query.
From the docs:
if you want to implement more interesting database allocation behaviors, you can define and install your own database routers.
A database router class implements up to four methods:
db_for_read(model, **hints)
db_for_write(model, **hints)
allow_relation(obj1, obj2, **hints)
allow_migrate(db, app_label, model_name=None, **hints)
From the documentation:
allow_migrate(db, app_label, model_name=None, **hints)
Determine if the migration operation is allowed to run on the database with alias db. Return True if the operation should run, False if it shouldn’t run, or None if the router has no opinion.
It is possible that one of the database routers in sequence is returning False for the migration that you're trying to run, in which case the particular operation will not be run.
I find Django migrations a bit of a mystery, and tend to prefer external tools (liquibase, for example).
However, I just ran into this "No migrations to apply" problem as well. I also tried removing the migrations folder, which doesn't help.
If you've already removed the migrations folder, here's an approach that worked for me.
First, generate the new "clean" migrations:
$ python manage.py makemigrations foo
Migrations for 'foo':
dashboard/foo/migrations/0001_initial.py
- Create model Foo
- Create model Bar
Then look at the SQL and see if it looks reasonable:
$ python manage.py sqlmigrate foo 0001
BEGIN;
--
-- Create model Foo
--
CREATE TABLE "foo" ("id" serial NOT NULL PRIMARY KEY, ... "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL);
CREATE INDEX "..." ON "foo" (...);
COMMIT;
Then apply execute that same SQL on your database.
I'm using Postgres but it will be similar for other engines.
One way is to write the content to a file:
$ python manage.py sqlmigrate foo 0001 > foo.sql
$ psql dbname username < foo.sql
BEGIN
CREATE TABLE
CREATE INDEX
COMMIT
Another is pipe the SQL directly:
$ python manage.py sqlmigrate foo 0001 | psql dbname username
Or copy and paste it, etc.
pip install django-extensions
and add this in the install app of settings.py
INSTALLED_APPS = [
'django_extensions'
]
Then run
python ./manage.py reset_db
Then run migrations again
python manage.py makemigrations
python manage.py migrate
Now, run migrations for your installed apps
python manage.py makemigrations your_app_name
python manage.py migrtate your_app_name
Done! See Your Database...
In addition to the other answers, make sure that in models.py, you have managed = True in each table's meta
You can remove your db
python manage.py makemigrations
python manage.py migrate
python manage.py migrate --run-syncdb
and see your data base this is working :)
Similar to Andrew E above but with a few changes especially where you haven't deleted the migrations folder in your quest to resolve the issue
1 - In your intact migration folder just examine the 000*.py files counting from the highest down to initial.py till you find the one where your Model is defined, say 0002_entry.py
2 - python manage.py sqlmigrate app-name 0002 > 0002_sql.txt to capture the SQL commands
3 - Edit this file to ensure there are no hard CR/LFs and the ALTER, CREATE INDEX commands are each on own single line
4 - Log into your DB (I have Postgres) and run these commands
In Database delete row myproj from the table django_migrations.
Delete all migration files in the migrations folder.
Then run python manage.py makemigrations and python manage.py migrate commands.
I am trying to move my django project into a production environment and in doing so I switched from using sqlite to postgres. In my development environment, whenever I made changes to my models or anything that would significantly change how the database was setup, I would literally just drag my sqlite file to the trash and just run syncdb to create a new empty one (probably bad practice). Now that I am using postgres, I am wanting to do the same thing without actually deleting the database. Basically I was wondering if there was a way to completely empty it or clear it out and then just run syncdb and start over?
I also welcome any alternative suggestions that might lead me down the right path, I'm very new to this.
You can use flush. Just run this command:
python manage.py flush
First if you have initial data in your database you can use dumbpdata command:
python manage.py dumpdata > initial_data.json
For specific app run:
python manage.py dumpdata <app_name> > initial_data.json
Second run the flush command to clean your database:
python manage.py flush
Third and last, run loaddata command to load the initial data into your database and create superuser by running createsuperuser command
python manage.py loaddata initial_data.json
python manage.py createsuperuser
In case flush does not work, you can drop the whole database.
Go to windows command line.
If server is 'postgres' and db name is 'mydb', run:
C:\> psql -U postgres
You will see a postgres-# prompt. Next is to close connections running the following:
SELECT * FROM pg_stat_activity WHERE pg_stat_activity.datname='mydb';
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'mydb';
Drop database once for all: DROP DATABASE mydb;
I am using Django with Postgres and Heroku. and I have a post table with looks something like this.
class Post( models.Model ):
.
.
content1 = models.CharField(max_length=1000)
.
One of my friends told me that limit is too small, now I want to change that maxlength to 10000. One way I can think of alternating the table by creating a new column named content2 then copying the content from content1, then deleting content1. I am fairly new to this and was wondering what was the best way to approach this problem.
Also is 10000 is a good length for a blog post? :D
You can either use dumpdata to save the data to a json-file and reload it after you re-create it, you can also manually ALTER the table with the new parameters. Or you can use south.
South provides databas migrations (as its called to change a table layout) for django.
pip install south
Add south to INSTALLED_APPS then run
python manage.py schemamigration --initial your_app_name
python manage.py migrate --fake your_app_name
Do your changes to the models.py, then run
python manage.py schemamigration --auto your_app_name
python manage.py migrate your_app_name
Now if you have the same database layout to change on several machines, check in the created migrations-files to git and run the "migrate" commands on all the machines that needs to update.