How to deal with old pip requirement in Django South migrations? - django

I have an app which is managed with South for quite a while. At one point of the development, I added a custom field to a model that had a pip requirement (sorl-thumbnail), but I removed this requirement later. My problem is that when I try to migrate this app in a fresh new database, South shouts:
./manage.py migrate my_app
...
ValueError: Cannot import the required field 'sorl.thumbnail.fields.ImageField'
How am I suppose to deal with this old requirement?

Maybe a dirty solution but if you really want to get rid of your sorl-thumbnail dependency you don't have much choice :
Locate the migration file in which the field was added and replace sorl.thumbnail.fields.ImageField by something like django.db.models.fields.files.ImageField
It should work unless you have DataMigrations depending on special features of sorl-thumbnail.

Related

What is the recommended way to run South migrations before Django 1.7 migrations?

I have a few projects with lots of South migrations, including ones that contain a fair amount of custom SQL that need to be run in a specific order. After upgrading to Django 1.7, this is the recommendation on how to convert a project to use South (from the Django documentation):
If you already have pre-existing migrations created with South, then the upgrade process to use django.db.migrations is quite simple:
Ensure all installs are fully up-to-date with their migrations.
Remove 'south' from INSTALLED_APPS.
Delete all your (numbered) migration files, but not the directory or __init__.py - make sure you remove the .pyc files too.
Run python manage.py makemigrations. Django should see the empty migration directories and make new initial migrations in the new format.
Run python manage.py migrate. Django will see that the tables for the initial migrations already exist and mark them as applied without running them.
In short, "wipe your existing migrations and Django will take care of the rest".
What is not mentioned here is what to do when existing South migrations don't only consist of model changes, but instead contain direct SQL, data migrations, etc, that need to be run in order. In this case, the auto-generated Django migrations will miss a lot of things, since not all of these changes are obvious from introspecting a models file.
Ideally, one would be able to run the existing migrations using South, and then have Django migrations take over. What might be the best way to go about this? If this is not possible or very much not recommended, what is the best alternative?
Maybe this post can help you. Essentially you have to:
Change your current migration directory from 'migrations' to 'south_migrations'
Update your settings with this line
SOUTH_MIGRATION_MODULES = {
'your_app': 'your_project.your_app.south_migrations',
}

Django: update database schema without losing data

What is the best solution if I want to upgrade (alter) my database schema (add new fields to tables by adding them just to Django models) without losing data in these tables? "syncdb" not adding them of course, so I need your advices how to alter tables without deleting them and recreating again with syncdb.
When south isn't an option I just manually write scripts for small changes. and big ones i use
./manage.py dumpdata appname
http://docs.djangoproject.com/en/dev/ref/django-admin/#dumpdata-appname-appname-appname-model
Throw that into a file. Run a regex replace to update any added /removed fields and then a reset of that app is possible. I have to admit i haven't done this in a while but i can get some specific code to do this for you if needed.
it loads back up with loaddata
edit
Django dump data for a single model? This Question is similar and might have the info i was talking about.
Still let me know if you need and i'll dig up my old script (or write out a nice simple one) for you.
UPDATE
./manage.py dumpdata appname --indent=4 > appname.json
#open your fav text editor and do a find/replace
./manage.py reset appname
./manage.py loaddata appname.json
That should do it. When you do a find replace you only need to remove fields that you don't have any more and add fields that aren't nullable. (as a minimum).
Notes: the --indent=4 nicely formats everything for you. It means 4 spaces.
the ./manage.py reset only works in pre django 1.3 (gah!) in django 1.3 you will have to do a ./manage dbshell and drop table. The sql for that is found from command ./manage.py sqlreset appname.
Learning curve...
http://south.aeracode.org/
South was merged into django core at version 1.7.
There is now a native django feature for data migration on schema changes.
Django 1.7 has built-in migrations support.
See https://docs.djangoproject.com/en/dev/releases/1.7/#schema-migrations

Adding fields to an already existing database for Django (version < 1.7)

I'm using Django ( < v1.7), with SQLite3 as the database engine.
I am trying to add a new field to an already existing model's class. This class already has data associated to it.
manage.py syncdb is not adding the new fields to the db.
Is there was a way to:
Add the new Field to the already existing class, and make sure a db entry is allocated to it?
Populate this new field with an empty string for all the already existing db entries?
This answer is still getting visibility but is outdated. Since 1.7 Django ships with a built-in migration system, written by the same author as South, and has deprecated syncdb though it will still work.
You will simply need to run a few commands to automatically add new columns:
python manage.py makemigrations
python manage.py migrate
It will be useful to understand what's happening under the hood, but those are the basics. Please ask new questions to get answers on 1.7 and migrations if you are still reading this old post.
For django < 1.7
syncdb will not add any new columns. See
http://docs.djangoproject.com/en/dev/ref/django-admin/#syncdb
You will have to add them manually. For example,. replace <> with relevant info:
python manage.py dbshell
ALTER TABLE <appname_modelname> ADD COLUMN <column_type> DEFAULT '';
You can see what Django might have done to generate columns on a fresh syncdb by using:
python manage.py sqlall app_name
and copying and pasting ALTER TABLE statements from there.
Otherwise, you can look into third-party apps like Django-South which are database migration tools.
Install south in your django and you can easily handle the existing tables. check this
If you really want to use Django-South, install it on your django, after adding your new fields to your existing model run
python manage.py schemamigration --initial
It will create a file in your project app. then,
python manage.py migrate
thats it your table is altered.
There are other options of migration apps (although South is the most used).
I have used django-evolution for my projects and it was very easy to install and start using.
South seems to be more complete, but for simpler tasks, django-evolution may be suitable.

south migration error app "is not available in this migration"

This problem is basically the same as the previous question
here.
However, the answer there does not work for me. I've installed the trunk version of south, manually entered the import line in the migration file in question, and done a full 'startmigration' in a separate directory and examined the 0001_initial.py file.
I have a Django project with several applications in it, one of them (named 'core') being referred to by the others. The south migration is trying to create a new table, with a column that has a foreign key to a model in core.
I'm currently importing core in the migration in question (0006), and I even added it to migration 0001, although it doesn't seem like that should matter.
Before I do something drastic, like removing that field, running the migration, and adding the field manually, is there a known manual workaround for fixing this south issue?
You probably did not use the --freeze option like this:
python manage.py startmigration <appname> migrate_core --freeze core
Having created a migration like so:
./manage.py startmygration appname --model NewModel
This error occurs:
"The model 'program' from the app 'core' is not available in this migration."
Recreating the migration like this fixes it:
./managepy startmigration appname --model NewModel --freeze core.Program
Just doing "--freeze core" did not do the trick for me.
You can receive this error by trying to access a class that resides in another django app. Check to make sure the class you are trying to access is in the models dictionary.

What is the best way to migrate data in django

After making some changes in my models (eg. new field in a model and a new model) what is the best way of reflecting these changes to my populated database?
PS: I wanted to see many solutions in one place rated. Apparently more solutions are already listed here.
Another technique is to use the dumpdata and loaddata arguments to manage.py, killing your database in-between:
python manage.py dumpdata > dump.json
With an external tool, drop any affected tables, or kill the whole db
python manage.py loaddata dump.json
See manage.py docs for more.
I've asked a similar question here and got quite a few answers.
There are quite a lot of ways of doing it, like manually doing the dumping and reloading with SQL, using fixtures or using one of the "emerging" schema-evolution packages for Django:
Django Evolution
South
dmigrations
(there's a DjangoCon video of a panel on schema-evolution in Django where these 3 solutions are discussed)
Depends on the scope of the changes. If it's beyond an ALTER, you're doing major surgery. Make backups of model as well as database so you can go back.
My preference is to put your new (revised, corrected, expanded) model in as a NEW application. It won't have URL's or anything, just a model.
Creating the new model as a new application. Create tests, just to be sure it works.
syncdb to build this interim implementation of the new model.
Write a little one-time utility to query your old model, and load your new model. You might want to try this in pure SQL. I prefer to write a simple query, build and save loop.
After the new model is loaded, you can dump this to a JSON file.
Once you've pulled the data out of your old model, you can rebuild your DB in the preferred new format.
Move the new model into your existing application.
Drop the old versions of the application's tables.
syncdb to build the new tables.
Load the JSON file with the data.
Django now has its own built-in migrations, documented at:
https://docs.djangoproject.com/en/dev/topics/migrations/
Look with manage.py sqlall what the parameters are for the new columns and manually add them in your database with Alter table statements. This way you don't have to redo your database; It requires some SQL knowledge though...
Take a look here (Scroll down to "Making Changes to a Database Schema")
Perform these steps in order may help you:
For more details,
clickhere: http://south.readthedocs.org/en/latest/
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
Then migrate the files to the database.