from django.db import models
from datetime import datetime
from django.contrib.auth import get_user_model
User = get_user_model()
class Blog(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
headline = models.CharField(max_length=250)
content = models.CharField(max_length=2050)
time_created = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.user.username
every time I migrate this
"(venv) PS C:\Users\user\Desktop\APPS\web_app_project> python manage.py makemigrations"
I always get this message:
"It is impossible to add a non-nullable field 'user' to blog without specifying a default. This is because the database needs something to populate existing rows. Please select a fix:
- Provide a one-off default now (will be set on all existing rows with a null value for this column)
- Quit and manually define a default value in models.py.
Select an option:"
How do I go about this
CodePudding user response:
Because you've added the non-nullable field user
to Blog
Django needs to add a user to all instances of blogs in the database, both new ones and existing. If you've created a blog instance in the database, what should Django do with its new user column? That's what it is asking you.
Only if there is no data in the database or you are completely OK with losing data, you can migrate your app to zero with python manage.py migrate <your app name> zero
(You might want to reverse to migration besides zero
. You can read more about reverse migrations). This will effectively undo all of your migrations for that app. You can then delete the existing migrations for that app and run makemigrations
again. Django will no longer complain about the non-nullable field user
, as this results in a migration that creates a Blog
table with a user field, instead of a migration that attempts to add a user
field to an existing Blog
table. Once again, do not do this unless you are OK with losing data. This should never be done if your app is already running in production, but it is OK if you have never deployed the app and have no "real" data, and you are still in the initial development phase. Also, make sure you have a backup of deleted migrations in case you need to add them back.
As others have suggested, you can create a default user model that is used as the one-time default to add user
s to Blogs
. For example (in Django shell)
from django.contrib.auth import get_user_model
User = get_user_model()
user = User(username='default_blog_user')
user.set_unusable_password() # Nobody should be able to log in as this user
user.save()
print(user.id) # keep this ID
Then, in the migration, you can use whatever that user.id
value was as the one-time-default. But this once again assumes that you haven't deployed to production, as the one-time-default and the IDs in development and production may not match.
If you have already deployed to production, I think the only thing you can do is make the user field nullable for the sake of your migration, but assert that it is not null in your programming logic. For example, by adding a validator to the field.
Side note: instead of running get_user_model
in your models
module, you should do this:
from django.conf import settings
class Blog(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
# etc.
When you define a foreign key or many-to-many relations to the user model, you should specify the custom model using the AUTH_USER_MODEL setting.
CodePudding user response:
You could probably get away with adding the user manually by using the python shell
• python manage.py shell
then import the required models.
Read more from a similar question here:
How to use the python shell
https://stackoverflow.com/a/5150535/15383032
CodePudding user response:
Maybe add a UUID to your User Model and make the fields that require a user in other models a CharField that stores the Users UUID.