11

I am using South with Django for database migrations.

In my models.py I changed one of the fields from

class User(models.Model):
    group = models.ForeignKey(Group)

to

class User(models.Model):
    group = models.ForeignKey(Group, null = True, blank = True)

In other words, I wanted to make the group field for User optional.

Then when I tried to run a schemamigration, South gave me this error

(doors)hobbes3@hobbes3:~/Sites/mysite$ python manage.py schemamigration doors --auto
 ? The field 'User.group' does not have a default specified, yet is NOT NULL.
 ? Since you are making this field nullable, you MUST specify a default
 ? value to use for existing rows. Would you like to:
 ?  1. Quit now, and add a default to the field in models.py
 ?  2. Specify a one-off value to use for existing columns now
 ?  3. Disable the backwards migration by raising an exception.
 ? Please select a choice: 

Why is South complaining? Didn't I specify a default of NULL with null = True and blank = True?

In case it matters this is what my current table looks like for doors_user

mysite=# \d doors_user
                                    Table "public.doors_user"
   Column    |           Type           |                        Modifiers                        
-------------+--------------------------+---------------------------------------------------------
 id          | integer                  | not null default nextval('doors_user_id_seq'::regclass)
 group_id    | integer                  | not null
 user_type   | character varying(1)     | not null default 't'::character varying
 comment     | text                     | not null
 email       | character varying(75)    | not null
 password    | character varying(135)   | not null
 first_name  | character varying(135)   | not null
 last_name   | character varying(135)   | not null
 phone       | character varying(135)   | not null
 status      | character varying(1)     | not null default 'p'::character varying
 location_id | integer                  | 
 t_created   | timestamp with time zone | not null
 t_modified  | timestamp with time zone | not null
Indexes:
    "doors_user_pkey" PRIMARY KEY, btree (id)
    "doors_user_group_id" btree (group_id)
    "doors_user_location_id" btree (location_id)
Foreign-key constraints:
    "group_id_refs_id_2fde5e861cc0e5fe" FOREIGN KEY (group_id) REFERENCES doors_group(id) DEFERRABLE INITIALLY DEFERRED
    "location_id_refs_id_13c85dcc5cba5e23" FOREIGN KEY (location_id) REFERENCES doors_location(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
    TABLE "doors_property" CONSTRAINT "owner_id_refs_id_7a3a10af3eba8739" FOREIGN KEY (owner_id) REFERENCES doors_user(id) DEFERRABLE INITIALLY DEFERRED
    TABLE "doors_order" CONSTRAINT "user_action_id_refs_id_79506d7c5228f713" FOREIGN KEY (user_action_id) REFERENCES doors_user(id) DEFERRABLE INITIALLY DEFERRED
    TABLE "doors_order" CONSTRAINT "user_created_id_refs_id_79506d7c5228f713" FOREIGN KEY (user_created_id) REFERENCES doors_user(id) DEFERRABLE INITIALLY DEFERRED
    TABLE "doors_log" CONSTRAINT "user_id_refs_id_3ce582a126688737" FOREIGN KEY (user_id) REFERENCES doors_user(id) DEFERRABLE INITIALLY DEFERRED
    TABLE "doors_ordercomment" CONSTRAINT "user_id_refs_id_6d10d6e79572e14d" FOREIGN KEY (user_id) REFERENCES doors_user(id) DEFERRABLE INITIALLY DEFERRED

And the SELECT statement

mysite=# select * from doors_user;
 id | group_id | user_type | comment |      email       | password | first_name | last_name | phone | status | location_id |          t_created           |          t_modified           
----+----------+-----------+---------+------------------+----------+------------+-----------+-------+--------+-------------+------------------------------+-------------------------------
  1 |        1 | w         |         | blah12@gmail.com | ads      | Michael    | Anderson  |       | a      |             | 2012-03-04 06:44:44.97263-05 | 2012-03-04 06:44:44.972661-05
(1 row)
hobbes3
  • 28,078
  • 24
  • 87
  • 116
  • I bypassed the problem by selecting option #3, but I would still like to know why South was complaining... – hobbes3 Mar 04 '12 at 18:39
  • Just a comment on your code, it's not good to have spaces in the brackets except after a comma. Not necessary, but it's in the python style standards, and its better for readability. – tushar747 Jan 06 '14 at 14:15
  • @tushar747 Yes, this is old code. I don't write like that anymore. I've updated the style. Thanks! – hobbes3 Jan 07 '14 at 01:06

1 Answers1

11

I think... South is thinking in case you wanted to rollback your migration to when you had

class User(models.Model):
    group = models.ForeignKey(Group)

In this case what would the default value have to be if it was rolled back. You chose option #3 which I believe disables the ability to rollback to that migration thus fixing your problem that way.

hobbes3
  • 28,078
  • 24
  • 87
  • 116
darren
  • 18,845
  • 17
  • 60
  • 79
  • Hmm that kind of make sense... But I think South should only warn if I change the (can be) NULL foreign key back to NOT NULL foreign key. Beside how are you suppose to have a default for a foreign key anyway? Choose a random id? – hobbes3 Mar 05 '12 at 01:33
  • 1
    You are correct. I've often wondered how I should pick a default for an FK. I've had a lot of trouble, sometimes having to redo my data because of that. I first created an item in the FK table then I run my migration with a default if need be. I'm sure it's not the best way though. – darren Mar 05 '12 at 08:42