'NOT NULL constraint failed' after adding to models.py - python

I'm using userena and after adding the following line to my models.py
zipcode = models.IntegerField(_('zipcode'),
max_length=5)
I get the following error after I hit the submit button on th signup form:
IntegrityError at /accounts/signup/
NOT NULL constraint failed: accounts_myprofile.zipcode
My question is what does this error mean, and is this related to Userena?

You must create a migration, where you will specify default value for a new field, since you don't want it to be null. If null is not required, simply add null=True and create and run migration.

coldmind's answer is correct but lacks details.
The NOT NULL constraint failed occurs when something tries to set None to the zipcode property, while it has not been explicitly allowed.
It usually happens when:
Your field has Null=False by default, so that the value in the database cannot be None (i.e. undefined) when the object is created and saved in the database (this happens after a objects_set.create() call or setting the .zipcode property and doing a .save() call).
For instance, if somewhere in your code an assignment results in:
model.zipcode = None
This error is raised.
When creating or updating the database, Django is constrained to find a default value to fill the field, because Null=False by default. It does not find any because you haven't defined any. So this error can not only happen during code execution but also when creating the database?
Note that the same error would be returned if you define default=None, or if your default value with an incorrect type, for instance default='00000' instead of 00000 for your field (maybe can there be an automatic conversion between char and integers, but I would advise against relying on it. Besides, explicit is better than implicit). Most likely an error would also be raised if the default value violates the max_length property, e.g. 123456
So you'll have to define the field by one of the following:
models.IntegerField(_('zipcode'), max_length=5, Null=True,
blank=True)
models.IntegerField(_('zipcode'), max_length=5, Null=False,
blank=True, default=00000)
models.IntegerField(_('zipcode'), max_length=5, blank=True,
default=00000)
and then make a migration (python3 manage.py makemigration <app_name>) and then migrate (python3 manage.py migrate).
For safety you can also delete the last failed migration files in <app_name>/migrations/, there are usually named after this pattern:
<NUMBER>_auto_<DATE>_<HOUR>.py
Finally, if you don't set Null=True, make sure that mode.zipcode = None is never done anywhere.

If the zipcode field is not a required field then add null=True and blank=True, then run makemigrations and migrate command to successfully reflect the changes in the database.

In Django Null=True means Null Values are accepted. But Some Filed having Django that Blank=True are not satisfied for put Blank fields.
DateTimeField
ForeignKey
These two fields are used and if you want to put Blank I recommend adding NULL=TRUE

Since you added a new property to the model, you must first delete the database. Then manage.py migrations then manage.py migrate.

Related

Why do I get an error when I try to add a new object?

I added a field that is a foreign key called user in a model but I initially received an error that said:
It is impossible to add a non-nullable field 'user' to bid without specifying a default.
So I made the default the string 'user'. However, instead I have been receiving the error:
ValueError: invalid literal for int() with base 10: 'user' when I try to migrate the changes I have made (python3 manage.py migrate).
And when I try to add a new bid, I get an error in the web page:
OperationalError: no such column: auctions_listing.user_id
How do I fix this?
models.py:
class Bid(models.Model):
item = models.ForeignKey(Listing, on_delete=models.CASCADE)
price = models.FloatField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
The fundamental reason you're getting the error is because you have provided a string to an IntegerField.
The real reason you have a problem is because you have tried to run migrations with a new non-nullable field without providing Django with a suitable default value.
When you run the migrations, Django needs to populate the new fields on existing objects with something as it can't enter null. It probably asked you in the terminal whether you would like to provide a default - you entered 'user' when what it wanted was a user_id integer (1, 2, 3, etc.).
This may not be the option you want as you would end up assigning all of the existing items to one particular user. Your fix would be to:
Remove the migration you have tried to apply
Allow the field to be nullable in your code
Re-run the migrations
Assign your desired users to each existing object
Remove the null=True from the field
Run another migration
If it doesn't matter that a particular user would be temporarily allocated all the objects then you can skip the nullable step and just pass a default ID when asked and change them after the migration has been run. You might not want to do this if it will affect current users of your application.
first error:
It is impossible to add a non-nullable field 'user' to bid without
specifying a default.
You faced This error because you already have some records in your database and they didn't have this new field/column 'user', so when you tried to add 'user' field to this table without having null=Ture for it, something like:
user = models.ForeignKey(User, null=True, Blank=True, on_delete=models.CASCADE)
what will happen to the old records? because they didn't have that column already and you didn't provide that new field/column as an unrequired field/column so you should provide a default value for the old record in migrating flow.
second error:
ValueError: invalid literal for int() with base 10: 'user
The Django ORM by default uses integer type for id/pk field of tables, so when you are creating a foreign key in your tables because it refers to a integer field so it should be integer as same as id/pk, (you can set custom type for your foreign keys in Django tables if you want)
Because you provide an string as default for existing records so you entered corrupted data in your table
third error:
OperationalError: no such column: auctions_listing.user_id
This happened because you migration flow faced issues and Django couldn't create new migration for your table
What should you do:
if existed data is not important to you:
truncate your database/table
remove your app migrations
create migrations again
else:
find the existed rows that you create a wrong default value for them
update them with existed users ids (integer value) or add a default integer value in your model field that refers to the your target user, like
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)

I'm getting an error message when making migration to db in django

hello guys I'm doing a django tutorial and i missed a change the instructor did in models.py so i fix it but when trying to make the migration to the db it gives me a code that I don't understand or i don't know what to do, here is what it says:
(tonyto) PS E:\web-dev\Python\Django1\myappito> python manage.py makemigrations
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
they way it was
name: models.CharField(max_length=100) details: models.CharField(max_length=500)
and this is how i update it
name: models.CharField(max_length=100) details: models.CharField(max_length=500)
thank you in advance.
This was caused because you're trying to migrate a model field that cannot be null, but since it cannot be null, it needs a default value so that django can replace all the existing rows with the null value of that field.
You have two options:
Provide the default by hand, and the django it's going to replace all the null values of that field with this
Set a default value in the model, example:
number = models.IntegerField(default=1)
string = models.CharField(default='')
first approach
this comes because you run the migration on each field created so the previous created filled doesn't accept null value so you want to provide default value in your case it is string value
you can choose the first choice and but the answer to be "default" with a quotation to understand it as a string
The second solution
delete the latest file created in the migration folder and
modify your model to be
'''
name = models.CharField(max_length=100,null=True)
details = models.CharField(max_length=500, null=True)
'''
then run the migration again
python manage.py makemigration
python manage.py migrate
then go back to model again and remove null from each field and run
python manage.py makemigration
python manage.py migrate

How to remove a non-nullable field in Django?

I've got a category field in my model which I want to remove. However it did not have null=True so (from previous experience) deleting it will cause a django.db.utils.IntegrityError: null value in column “category” violates not-null constraint error.
Any way around this?
Here's is the field:
class Post(models.Model):
...
category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, default='1')
You must be run the manage.py makemigrations
And manage.py migrate to apply the changes
By default when you create a new django field and if you don't provide the argument null explicitly, it will be treated as False, so if you don't specified null argument at the creation it will be by default null = False. Just delete the field,save the file and make the python.manage.py makemigrations and then python.manage.py migrate to reflect the changes you have made to your model in the DB

Django 2.0: sqlite IntegrityError: FOREIGN KEY constraint failed

I'm working on adding Django 2.0 support to the django-pagetree library. During automated testing, using an sqlite in-memory database, I'm getting a bunch of errors like this:
File "/home/nnyby/src/django-pagetree/pagetree/tests/test_models.py", line 638, in setUp
'children': [],
File "/home/nnyby/src/django-pagetree/pagetree/models.py", line 586, in add_child_section_from_dict
...
File "/home/nnyby/src/django-pagetree/venv/lib/python3.5/site-packages/django/db/backends/base/base.py", line 239, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
This is noted in the Django 2.0 release notes: https://docs.djangoproject.com/en/2.0/releases/2.0/#foreign-key-constraints-are-now-enabled-on-sqlite
From that description, which I don't fully understand, this shouldn't apply for test databases that aren't persistent, right? Wouldn't my sqlite test db get created with the appropriate options when using Django 2.0?
The app settings I'm using for testing are here: https://github.com/ccnmtl/django-pagetree/blob/master/runtests.py
The documentation says two things:
If you have ForeignKey constraints they are now enforced at the database level. So make sure you're not violating a foreign key constraint. That's the most likely cause for your issue, although that would mean you'd have seen these issues with other databases. Look for patterns like this in your code:
# in pagetree/models.py, line 810
#classmethod
def create_from_dict(cls, d):
return cls.objects.create() # what happens to d by the way?
This will definitely fail with a ForeignKey constraint error since a PageBlock must have section, so you can't call create without first assigning it.
If you circumvent the foreign key constraint by performing an atomic transaction (for example) to defer committing the foreign key, your Foreign Key needs to be INITIALLY DEFERRED. Indeed, your test db should already have that since it's rebuilt every time.
I met a different situation with the same error. The problem was that I used the same Model name and field name
Incorrect code:
class Column(models.Model):
...
class ColumnToDepartment(models.Model):
column = models.ForeignKey(Column, on_delete=models.CASCADE)
Solution:
class Column(models.Model):
...
class ColumnToDepartment(models.Model):
referring_column = models.ForeignKey(Column, on_delete=models.CASCADE)
Do you have add on_delete to your FOREIGN KEY? On Django 2.0 this argument is required.
You could see also:
https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete
https://docs.djangoproject.com/en/2.0/howto/upgrade-version/
https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_one/
https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey
In my case, I found that the ForeignKey object that my model refers to does not exist.
Therefore, I change the referenced FK object to the existing object.
A reason could be you miscalculated what happens when you delete an item from the db that is linked with a foreign key to something else, elsewhere.
p.e. what happens when you delete an author that has active books?
I don't meant to enter into the logic of the application, but consider for example to cascade the deletion of the elements linked to that key.
Here is an example, in this case we are dealing with "post" attribute for each "user"
user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
Here's a careful explanation, Django 4.0:
https://docs.djangoproject.com/en/4.0/ref/models/fields/
I just had this error: sqlite3.IntegrityError: FOREIGN KEY constraint failed on my Django project. Turns out I deleted the migrations folder somewhere along the line so it didn't pick up my model changes when I ran python manage.py makemigrations. Just make sure you still have a migrations folder with migrations in.
One more thing to check, in my case it was related to my fixtures files.
Regenerating them after migration to Django3 solved the issue I had while testing my app.
./manage.py dumpdata app.Model1 app.Model2 --indent=4 > ./app/fixtures/file.json
When I have trouble with migrations or tables, I do it and it very often helps:
Comment your trouble strings;
Do python3 manage.py makemigrations and python3 manage.py migrate;
Then u must do python3 manage.py migrate --fake;
Uncomment your strings and do it again python3 manage.py makemigrations and python3 manage.py migrate.
I hope it is useful for u
My problem was solved after doing the migration, because I have altered the foreign key and then didn't apply the migrations.
Specifically, at first I have the following piece of code in models:
class TeacherRequest(models.Model):
requester = models.ForeignKey(
Profile,
on_delete=models.CASCADE,
related_name="teacher_request",
)
class RequestStatus(models.TextChoices):
PENDING = '1', _('pending')
APPROVED = '2', _('approved')
REJECTED = '3', _('rejected')
status = models.CharField(
choices=RequestStatus.choices,
max_length=1,
default=RequestStatus.PENDING,
)
Then I have changed the foreign key from Profile to User:
class TeacherRequest(models.Model):
requester = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="teacher_request",
)
class RequestStatus(models.TextChoices):
PENDING = '1', _('pending')
APPROVED = '2', _('approved')
REJECTED = '3', _('rejected')
status = models.CharField(
choices=RequestStatus.choices,
max_length=1,
default=RequestStatus.PENDING,
)
Solution
python manage.py makemigrations
python manage.py migrate
Most probably the cause of the error is the lacking of matching Foreignkey elements in your model and the one your trying to save(update using that foreignkey).
Make sure that the foreignkey constraints(value) are present in both your and the new data
I met a different situation with the same error.
The problem was that i had my on_delete attributes set to DO_NOTHING, which ended up violating foreign key constraints.
Setting it to SET_NULL fixed it for me.

Django: non-nullable field without a default

In Django I use manage.py makemigrations and manage.py migrate on the following models.py file:
class Family(models.Model):
comment1 = models.CharField(max_length=80)
#comment2 = models.CharField(max_length=80)
After this successful initialization, I changed models.py to (I just uncomment the new model field which is basically a copy of the other model field):
class Family(models.Model):
comment1 = models.CharField(max_length=80)
comment2 = models.CharField(max_length=80)
Now when I try to makemigrations again I get the following error:
You are trying to add a non-nullable field 'comment' to family 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 Select an option:
Why didn't I get this error upon intialization in the first place?
Others are right. you should set a default value for that field.
but there is a a trick that you can solve this. but it is not a good way... only if you have no choice.
1. comment all of your table
2. run makemigrations and migrate
3. uncomment your table
4.2. run makemigrations and migrate again
image1=models.ImageField(upload_to='app/image12',help_text="hi", null=True)
That is, set null= True'in the field.
It happens when you change your model after stored database.
If you want to make it non nullable without default.
you have to provide value for the same field when you create migration file. thats why it asks for the option. type "1" in terminal while python manage.py makemigrations and then provide a value for the field for previously saved row(if any).
Let me know if this helps.
I have faced a same issue, in my case:
Focus on the alert:
...non-nullable field 'comment' to family...
model: Family
field: comment
Just add one more attr in the field comment of the model family:
default=''
You can add this: default=None or default="something"
or add null=True, blank=True.

Categories