0

I have a OnetoOne field with primary_key=True in a model. Now I want to change that to a ForeignKey but cannot since there is no 'id'.

From this:

user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)

To this:

user1 = models.ForeignKey(User, related_name='questionnaire', on_delete=models.CASCADE)

Showing this while makemigrations:

You are trying to add a non-nullable field 'id' to historicaluserquestionnaire without a default; we can't do that (the database needs something to populate existing rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py

So how to do that? Thanks!

Harshit verma
  • 506
  • 3
  • 25

3 Answers3

1

just delete your previous migrations

e.g 

    migrations:
          |
          |- 001.initail.py
          |- 002.examplefiles.py

you just have to delete you most recent migrations and

run the command

python3 manage.py makemigrations
python3 manage.py migrate
1

Django models have a default ID attribute. Since you changed the model, the previous data records has now conflicts with your new column attributes because when previous records were added, there were no ForeignKey. Remember, In your foreignkey, null values are not allowed. There are multiple fixes to your solution. Follow these step one-by-one and see what resolves your eror.

  • Delete your migrations file and run migrations again

Set NULL=True in your foreign key

OR

Delete previous records of the table to resolve the conflict, so that when you run migrations, it adds a default value of id itself

instead of deleting, you can also try and change your migrations files directly like this

https://stackoverflow.com/a/29074241/11979793

Hashir
  • 390
  • 5
  • 20
  • Problem is not with the migrations of ForeignKey field, problem lies in the delete of OnetoOne field since the primary_key is True – Harshit verma May 22 '20 at 09:58
  • Does this thread help? https://stackoverflow.com/questions/2055784/what-is-the-best-approach-to-change-primary-keys-in-an-existing-django-app – Hashir May 22 '20 at 10:14
  • Not that relevant, anyway I have solved it the bad way, by making a new models with the fields I wanted and tranfer the data. – Harshit verma May 22 '20 at 14:33
1

The problem is that your trying to remove the primary key, but Django is then going to add a new primary key called "id". This is non-nullable and unique, so you can't really provide a one-off default.

The easiest solution is to just create a new model and copy your table over in a SQL migration, using the old user_id to populate the id field. Be sure to reset your table sequence to avoid collisions.

natehawkboss
  • 113
  • 6
  • Didn't wanted to do that, thats why I have posted this It seems like there is no other option to do this Thanks! – Harshit verma Nov 10 '21 at 08:20
  • No matter how you handle it, don't forget to reset the sequence in your database so that you avoid collisions. If you want to try another way you are going to have to use a [SeparateDatabaseAndState](https://docs.djangoproject.com/en/4.0/ref/migration-operations/#separatedatabaseandstate) operation to add the id field state and probably just copy the user_id column in the database to id. – natehawkboss Jan 12 '22 at 00:43