0

I had a pre-existing model Item. I added a ForeignKey(User) to this model recently and now I am getting no such column: todo_item.user_id when I try to render pages.

Model:

class Item(models.Model):
    user = models.ForeignKey(User) # new
    name = models.CharField(max_length=60)
    created = models.DateTimeField(auto_now_add=True)
    priority = models.IntegerField(default=0)
    difficulty = models.IntegerField(default=0)
    done = models.BooleanField(default=False)

output from manage.py sqlall:

BEGIN;                                                                                                                                                               
CREATE TABLE "todo_item" (                                                                                                                                           
    "id" integer NOT NULL PRIMARY KEY,                                                                                                                               
    "user_id" integer NOT NULL REFERENCES "auth_user" ("id"),                                                                                                        
    "name" varchar(60) NOT NULL,                                                                                                                                     
    "created" datetime NOT NULL,                                                                                                                                     
    "priority" integer NOT NULL,                                                                                                                                     
    "difficulty" integer NOT NULL,                                                                                                                                   
    "done" bool NOT NULL                                                                                                                                             
)                                                                                                                                                                    
;                                                                                                                                                                    
CREATE INDEX "todo_item_6340c63c" ON "todo_item" ("user_id");                                                                                                        

COMMIT;  

I realize that manage.py syncdb will not alter my pre-existing table. And I understand that I could use South or something like it to avoid losing my data, but I am still in testing mode, and I don't care about any of the current data in my table. I am fine with wiping it clean to get this working. In fact I already have.

I've run:

python manage.py flush todo

and then

python manage.py syncdb

Which seems like it should've worked. After I ran flush it had me enter a new admin user, and all of my todo_item data is gone. But it doesn't seem to have killed the todo_item tables. After running these commands if I use PRAGMA table_info(todo_item) inside sqlite shell I don't see the user_id column listed.

My question is: beyond flush and syncdb what do I have to do in order to get the database to reflect changes to my model?

FoamyGuy
  • 46,603
  • 18
  • 125
  • 156
  • I am not able to mark it but i think its an duplicate to: [update django database to reflect changes in existing models][1] [1]: http://stackoverflow.com/questions/1985383/update-django-database-to-reflect-changes-in-existing-models – os_1 Feb 09 '14 at 23:27
  • @itconlor the question does seem very similar to that one. But the answer that dm03514 gives below is the actual solution to my problem. And isn't listed as an answer over on that question. – FoamyGuy Feb 09 '14 at 23:33

1 Answers1

2

Unfortunately, it looks like flush only deletes all the data in your database and then reloads your intial data. It does not delete your database/table and re run the create statements.

You can enter your db shell and manually drop your item table, (or your whole db).

python manage.py dbshell
DROP TABLE todo_item;

then rerun syncdb


On a side note- for years I avoided using south, and would just alter table or drop the table, and resync, but for my most recent project i decided to give it a try. South has a very small learning curve and is a very powerful too, because you never have to drop and resync your tables.

Once you have south initialized, to accomplish what you want to do, all that is necessary is:

python manage.py schemamigration yourapp
python manage.py migrate yourapp

No dropping tables, no databases, no reloading data, no recreateding super user everytime a model changes

dm03514
  • 54,664
  • 18
  • 108
  • 145
  • 1
    Yes, South is awesome - even while in "testing" mode. You can always throw out your previous schemamigration files later! – aldo Feb 09 '14 at 23:27
  • 1
    I have looked into south(and am stoked that it is getting added to django core) it is for sure on my list of things to learn very soon =). Still trying to make my way through some very beginner apps right now though. Once I've got my head wrapped around all of the components and how the interact together in "plain" django I'll start branching off into modules, with south probably being first among them. – FoamyGuy Feb 09 '14 at 23:30