First steps with PostgreSQL + Django + South - django

Hi Stackoverflow people,
In the past, I always developed my Django projects locally with sqlite as database platform. Now, I wanted to move to PostgreSQL to take advantage of GIS features, but the transition gives me huge grief.
I have installed postgresql similar to this post and then followed the GeoDjango description for the creation of the database.
Furthermore, I replaced the models class by
from django.contrib.gis.db import models
and add
geolocation = models.PointField(_('Geo Location'),
geography=True,
help_text=_('Geolocation with Longitude and Latitude'))
objects = models.GeoManager()
Now, before diving deeper into the postgreSQL sphere, I wanted to test the model access through the Django Admin, and I encountered the first error.
When I select the model (which i just modified as mentioned above) in the Admin, I get the following error:
**InternalError at /admin/remap/project/**
current transaction is aborted, commands ignored until end of transaction block
This error is connected with a wrong sql query, but I am surprised that the Django Admin creates wrong sql statements (used by million developers and it worked fine in the earlier sqlite config).
When I check the django sql statement, I can see the entry for the PointField
"geolocation" geography(POINT,4326) NOT NULL,
but when I check psql \d projects, I can't see the change to the PointField (this is what should cause the error). Since I am using South, I executed
./manage.py schemamigration projects --initial
./manage.py migrate projects
but I get the message
Running migrations for projects:
- Nothing to migrate.
- Loading initial data for projects.
How can I convince south / postgresql that there is something to migrate?
Do you see any other problem with the transition form SQLite to PostgreSQL?
Thank you for your answer & help!

A possible answer:
Did you syncdb? Often when I'm having trouble with south, I just delete the database and run manage.py syncdb from scratch to make sure all my columns are in line. If you want south to ignore migration-enabled apps and just syncdb up to the current version, you can use manage.py syncdb --all

Related

django - schema migration - how to add a field

I have a django 1.8 app working with a db.
I'm trying to change the schema of a table using the built-in migration.
Here are the steps I did:
In my dev invironment, I grabbed the app source and ran
python manage.py sycdb
then I ran
python manage.py loaddata ~/my_data.json
then I modified modes.py. Added a field and renamed a field...all from the same table 'TABLE1' which had no data.
then
python manage.py makemigrations myapp
python manage.py migrate
Error: django.db.utils.OperationalError: table "myapp_someother_table" already exists
then ran
python manage.py migrate --fake-initial
worked!
but when I browsed to the admin page for TABLE1, I get this error:
OperationalError: no such column: myapp_table1.my_new_field_id
I checked the db and yes, there is no such column.
How can I procceed from here? I prefer to fix this via django.
If I fix it straight in the db, then the migration goes out of sync.
Migrations do not automagically see that you have made changes. Migrations detect changes by comparing the current model with the historical model saved in the migration files.
In this case, you didn't have any historical models, since you didn't have any migrations. Django was not able to detect any changes in your models, even though they were different from your database.
The correct way to make changes to your model is to first run manage.py makemigration <my_app>, and then make the changes to your model, followed by another manage.py makemigrations.
You might not be able to do it via pure django and keep your data. I don't have personal experience with south but there are a lot of mentions if this tool. Just in case if nothing else works for you...
Here is what I did to make things work, but there must be a better way so please add more answers/comments...
I deleted the sqlite db and the migration folder
I made the desired changes to model.py
ran syncdb
ran loaddata to load the json data dump that I had saved previously.
just started the dev server

Django 1.8 - what's the difference between migrate and makemigrations?

According to the documentation here:
https://docs.djangoproject.com/en/1.8/topics/migrations/ it says:
migrate, which is responsible for applying migrations, as well as unapplying and listing their status.
and
makemigrations, which is responsible for creating new migrations based on the changes you have made to your models.
From what I understand, I first do
makemigrations
to create the migration file and then do
migrate
to actually apply the migration?
Do note though that I just began my Django project and I added my app to my "installed_apps" list. After that, I did
python manage.py runserver
and it said
You have unapplied migrations; your app may not work properly until they are applied. Run 'python manage.py migrate' to apply them.
It didn't mention anything about running makemigrations.
According the Polls tutorial:
python manage.py makemigrations <app>: Create the migrations (generate the SQL commands).
python manage.py migrate: Run the migrations (execute the SQL commands).
As Django's documentation says Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema.
makemigrations basically generates the SQL commands for preinstalled apps (which can be viewed in installed apps in settings.py) and your newly created apps' model which you add in installed apps.It does not execute those commands in your database file. So tables doesn't created after makemigrations.
After applying makemigrations you can see those SQL commands with sqlmigrate which shows all the SQL commands which has been generated by makemigrations.
migrate executes those SQL commands in database file.So after executing migrate all the tables of your installed apps are created in your database file.
You can conform this by installing sqlite browser and opening db.sqlite3 you can see all the tables appears in the database file after executing migrate command.
As we know Django is an ORM (Object Relational Mapping). When we use the command:
python manage.py makemigrations [app_name]
It will generate the sql command to create the table corresponding to each class you made in models.py file.
then the command:
python manage.py migrate [app_name]
will create the table in database using the commands which have been generated by makemigrations.
For example, if we make a model class-
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
The corresponding sql command after using makemigrations will be
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
and using above command, table will be created in the database when we use migrate.
You should run the command -migrate- after adding a new app under the INSTALLED APPS section in the settings.py file in order to synchronize the database state with your current set of models. Assuming you've already modified the models.py file.
When you run -makemigrations- it packages up changes to your model into individual migration files.
Normally you would first run makemigrations and then migrate.
See documentation on Django Models
It is necessary to run both the commands to complete the migration of the database tables to be in sync with your models.
makemigrations simply analyzes your current models for any changes that would be out of sync with your database and creates a migrations file that can be used to bring the in sync. If left at this point, your models would still be out of sync with your database possibly breaking your code that queries the database.
migrate is the command to "Make It So!" and apply the changes noted during the makemigrations phase.
Source
This is django's replacement for the old manual south way of making migrations, they can be used to catalog changes in your models and write out changes that will take place in the db.
Migrate is basically the old syncdb but it takes into account all the migrations made by makemigrations.
makemigrations: creates the migrations (generating SQL Command- not yet executed)
migrate: run the migrations (executes the SQL command)
But in your case, Django is asking you to migrate the DEFAULT migrations which should run before first running of server. This would have been the same warning without even creating the first app.
Make migrations : Basically it generate SQL Commands for preinstalled apps and newly created app model which you added in installed app. It dose not executed SQL commands in your database. So actual tables are not created in DB.
Migrate : Migrate execute those SQL commands which are generated by make-migration in Database file . So after migrate all the tables of installed app are created in DB.
According to the second tutorial of the django tutorial series. Migrations are:
The migrate command takes all the migrations that haven’t been applied (Django tracks which ones are applied using a special table in your database called django_migrations) and runs them against your database - essentially, synchronizing the changes you made to your models with the schema in the database.
So pretty much all it does is:
When you execute the make migrations command you're saving the 'instructions' to mysql
When you execute the migrate command, you're executing those same instructions

How to get my database to reflect changes made to models.py?

I made a change to my models, and I cannot for the life of me figure out how to get my database to reflect my models. So far I have tried the following:
python manage.py shelldb
SELECT * FROM sqlite_master WHERE type='table';
DROP TABLE appname_modelname;
When I tried that I got: "unknown command: shelldb".
I also tried:
python manage.py dbshell
DROP TABLE accounts_userreview;
No error, but my db still doesn't reflect my models.
Finally, I just altogether deleted my database by dragging it into the trash and then doing syncdb, it then made me create a new superuser, but STILL the database that was created does not reflect the changes to my models.
I'm at a loss here, What else can I do here? Also, I'm new to learning Django, is there some kind of layer in between the models and my database? I would assume there is since deleting and then rebuilding the database didn't work.
Would appreciate any advice here.
if you are on Django < 1.7 , you have to use some migration tool i.e. - South . Django 1.7 has inbuilt migration.
For more info migrations
Run these commands in terminal to make migrations for Django 1.7
python manage.py makemigrations
python manage.py syncdb
for Django < 1.7
use South

How do I successfully integrate a second database with Django South?

One of our clients needs to add some geolocation data to their
site. Since they already have a database setup without GIS extensions,
I decided to create a new database (with the GIS extensions), which I
intend to use to store only the geolocation data.
I had, at some point, set things up to work alright on my development
machine (meaning, I have migrations for these new models). But now that the code has been written, I imported a DB dump
directly from the server so that my development machine exactly
mirrors the production machine, and now I can't seem to get South to
apply the migrations correctly. South seems to have several features
which allow for multiple databases, but none of them have worked so far.
What I've tried:
Just adding the model and migrating. This gives me the following
error:
AttributeError: 'DatabaseOperations' object has no attribute
'geo_db_type'
OK, so South is trying to create the model on the original database
which doesn't have the GIS extensions.
Adding the model, but specifying the 'geo' database for migrating
the 'geo' app. This gives me the following error:
django.db.utils.DatabaseError: relation "south_migrationhistory"
does not exist
I guess south expects its MigrationHistory table to exist on the 'geo'
database as well?
Allow south's models to exist on my 'geo' database.
$ python manage.py syncdb --database=geo
$ python manage.py migrate
This gives me the following error:
django.db.utils.DatabaseError: relation "<model>" already exists
I'm guessing this is because I already have MigrationHistories stored
in the other database?
South apparently has a sparsely documented feature called 'dbs'
(see:
http://south.aeracode.org/docs/databaseapi.html#accessing-the-api )
So I tried the previous three methods again replacing all instances of
"db" with "dbs['geo']".
a. Migrations run smoothly, but don't actually create any tables
in my 'geo' database.
b. Same error as when not using 'dbs' features.
c. Same error as when not using 'dbs' features.
This entire process has been extremely frustrating. Has anyone got
multiple database support up-and-running when using South?
Whenever I have modified the table models I used south and these commands to modify the structure and they always worked:
python manage.py convert_to_south "your_app"
python manage.py migrate "your_app"
I recommend running these commands after running syncdb, so your tables are created.

newbie difficulty using south with pycharm - DatabaseError: no such table: south_migrationhistory

I'm using sqlite3 and pycharm to learn more about django, and googled to find that south is recommended to make it easier to modify models after they have been created.
I'm trying to follow the advice on http://south.aeracode.org/docs/tutorial/part1.html#starting-off.
The most success I've had so far is to create a simple model and run syncdb before adding south to installed_apps. That way the intial tables are created and I get a chance to create a super user. (Django admin seems to fret if there are no users).
Then I add south to installed_apps, and run django_manage.py schemamigration bookmarks --initial
It seems to work fine. A new directory is created called migrations with a couple of files in it in my app folder and an encouraging message.
"Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate bookmarks"
The next step - django_manage.py" migrate bookmarks generates the following error message
django.db.utils.DatabaseError: no such table: south_migrationhistory.
I thought that table would be created in the first schememigration step. What am I missing? Can anyone help?
Marg
South uses a table if its own to keep track of which migrations have been applied. Before you can apply any migrations, this must have been created, using python ./manage.py syncdb.
As well as for setting up south, you will find syncdb sometimes necessary for non-south apps in your project, such as the very common django.contrib.auth.
Note that as a convenience, you can run both in one go like this
python ./manage.py syncdb --migrate
My latest (unsuccessful) effort was the following
Create application – synch db – superuser created
Test run –admin screen shows basic tables
Add south, and syncdb from command line with manage.py syncdb – south_migrationhistory table created. Add basic vanilla model
Tried various combinations of manage.py syncdb –manage, and
schemamigration from Pycharm (if run from within pycharm a
migrations directory is created within the app
– if run from the command line the directory does not seem to be
created.)
Django admin screen shows table – but if I try to edit
the table it says that it doesn’t exist
Check database structure
using SQLite browser - table for newly created model doesn’t exist
I’m starting to think that the whole thing is not worth the time wasting hassle – maybe I’m better off just modifying the tables in SQLite browser
Answer in the similar question:
Run syncdb to add the Django and South tables to the database.