Django BooleanField(default=False) Confusion - django

Can anyone help me out here? I am inserting data into my postgreSQL DB.
admin_created is a booleanfield set to false by default. I've provided a true value for the first workout, but left the second workout blank for the booleanfield. Based on my understanding it should automatically be set to false, but i'm getting the error message below. Any ideas on why this is happening?
#.sql
INSERT INTO main_app_workout(name, description, admin_created)
VALUES
('Yoga', 'Roll up your yoga mat and discover the combination of physical and mental exercises that have hooked yoga practitioners around the globe.', 'True');
INSERT INTO main_app_workout(name, description)
VALUES
('Boxing', 'Ready to get your sweat on? Learn the six basic punches to build the foundation of an experienced boxer.');
#models.py
class Workout(Model):
name = models.CharField(max_length=40)
description = models.TextField()
exercises = ManyToManyField(Exercise, blank=True)
admin_created = models.BooleanField(default=False)
#Error code
psql:db/create_main_exercises.sql:49: ERROR: 23502: null value in column "admin_created" of relation "main_app_workout" violates not-null constraint
EDIT:
Thank you all for the comments. My solution to this problem was to provide true values for the admin_created for the seeded data. In addition I changed the admin_created field to
admin_created = models.BooleanField(null=True, default=False)
When I create new instances of the model in Django it automatically sets it to False.

Django is builded to use the ORM, if you are doing this insertion manually, Django can't set the defaul value for you, so will be passed NULL.

The field based constraints are only placed at the code level in django not at the DB level.
So if you 'll create a object in django programmatically you 'll not face this issue. But when created using SQL you 'll face this issue.
Only a few constraints are available that you can apply at the DB level that too post django 2.2.
Check the constraints documentation for django here

Related

Why is unmanaged model not calculating id in Django?

I have an unmanaged model in Django:
class Person(models.Person):
name = models.CharField(max_length=200)
class Meta:
managed = False
db_table = '"public"."person"'
Somewhere in my tests, I try to create a Person entry in the DB:
person = Person(name="Ariel")
person.save()
But then I get an error:
django.db.utils.IntegrityError: null value in column "id" of relation "person" violates not-null constraint
DETAIL: Failing row contains (null, Ariel).
Outside tests, everything works fine. In the tests, I initialize the DB with the tables referenced by the unmanaged by loading a schema dump.
The Django docs states that "no database table creation, modification, or deletion operations will be performed for this model", and that "all other aspects of model handling are exactly the same as normal", including "adding an automatic primary key field to the model if you don’t declare it". But doesn't that mean this code should work? How come Django and Postgres are not taking care of the id? Am I doing something wrong? How can I fix it?
Surely the issue that you're having is that in your PostgreSQL table, id is not an auto incremental field and it nulls by default.
It's quite a common issue when using unmanaged models on Django. You need to cover every single aspect of the table you're using.

Is it safe to make a empty field non-empty for a existing database?

Hi, I'm trying to alter my current django project schema, the data migration tool is south. django version is 1.6.9.
It is a existing database so I don't want to mess up with my historical data.
What I'm trying to alter is making a blank=true field non-empty(blank=false)
here is my model class:
class Post(DraftableModel, EditTrackingModel):
title = models.CharField(max_length=120,
verbose_name='headline')
description = models.CharField(max_length=260,
blank=True,
verbose_name='lead-in',
help_text="260 character limit")
/*rest of the code*/
I want change the description from models.CharField(blank=True) to models.CharField(blank=False), which is the default blank value
considering the existence of my database, some of my old Post model do have empty description.
After my migration and change of database schema, will my database be corrupted?
When you try to migrate, django will warn you about those empty fields. so you have few options.
You can add a default value in your model like default="Some Default Value" and django will chose that default value for all empty fields on migration.
You can just send the migrate request and on the terminal, django will ask you to add an one-off value to be added to all the empty fields.
Also you can edit the migrate files and add different values for those empty fields based on conditions you have in mind.
You can write a function to check for all the empty fields for exiting rows and add some data based on some conditions.
Also i highly recommend to make a backup first. Doesn't matter how small the changes are or how good you are in coding.

django.db.utils.OperationalError: cannot ALTER TABLE because it has pending trigger events

I am trying to change accepted_answer ForeignKey to a BooleanField and while migrating getting the error django.db.utils.OperationalError: cannot ALTER TABLE "forum_thread" because it has pending trigger events. This is the models.py of before:
class Thread(models.Model):
title = models.CharField(max_length=300)
answer_count = models.PositiveIntegerField(default=0)
added_at = models.DateTimeField(auto_now_add=True)
accepted_answer = models.ForeignKey('forum.Post', null=True, blank=True, related_name='+')
This error seems to happen when trying to update and change schema of the same table in one operation.
For example, after providing new default values when prompted by makemigrations when removing null=True from a field, this error seems to appear because Django is trying to change nullability while also updating the column.
Workarounds, depending on situation:
Easiest is often adding a new field with the desired properties, then removing the old field (maybe after copying data over).
If the error can be avoided by setting values for all fields that were needing a new default value (Django asking during the migration), try setting those values before making the migration/schema change.
In your specific case, adding a new field then removing the old is probably the way to go.
Adding to Max Lemieux's answer, if you try to change a field from nullable to non-nullable, this is impossible in the same database transaction, thus:
you can split your operations into 2 migrations (not recommended if complex operations)
you can wrap your migration's operations with these two statements to force PostgreSQL to check null constraint on save and not at the end of transaction
operations = [
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE', reverse_sql='SET CONSTRAINTS ALL DEFERRED'),
... # your other operations here
migrations.RunSQL('SET CONSTRAINTS ALL DEFERRED', reverse_sql='SET CONSTRAINTS ALL IMMEDIATE'),
]

Django 1.9 - IntegrityError on update

class Configuration(models.Model):
configuration_key = models.CharField(max_length=100, unique=True)
configuration_value = models.TextField()
configuration_description = models.TextField("a brief description of this setting", blank=True)
The above is my model. I am able to able to add configurations using the admin. I have not configured any customizations on the admin. It is a very basic
admin.site.register(Configuration)
When I update an existing configuration with admin, it throws an IntegrityError
duplicate key value violates unique constraint "config_configuration_configuration_key_key"
DETAIL: Key (configuration_key)=(SAMPLE_CONFIGURATION) already exists.
My question: Shouldn't the admin know that an existing configuration is modified and handle this accordingly? Am I missing something? To be clear - SAMPLE_CONFIGURATION - there is only one such row in the table with that configuration_key. I am trying to edit the configuration_value for that row using the admin and it throws the Integrityerror.
Your code is just fine, there must be no error. Update Django to the current version and try again.
Also try to isolate the problem. Use tests to reproduce the issue. If tests are passed, then problem not in your code.
Double check what is inside DB, try to update row directly using SQL.
This test updates configuration_value without any integrity issues.
class ConfigurationModelTest(TestCase):
def test_uniq_issue(self):
config = Configuration.objects.create(configuration_key='SAMPLE_CONFIGURATION',
configuration_value='value')
config.save()
config.configuration_value = 'updated_value'
config.save()

Why does Django set the pk of all my models to '90'?

I'm running Django 1.5 with SQLite, and I have a model called Assignment. Whenever I create one, it gets created with the correct pk value. But, whenever I try to retrieve any Assignment from my database, it is always returned with a pk of 90. I've been fighting this for an hour, and I have to admit I'm completely confused.
Here's my code, if it's any use.
class Assignment(models.Model):
class Meta:
app_label = 'holiday'
unique_together = ('year', 'employee')
year = models.PositiveIntegerField(db_index=True)
employee = models.ForeignKey('bsc.Employee', db_index=True)
days = models.PositiveIntegerField(null=True)
This, and a bunch of methods that calculate some values based on models related to this one. Nothing fancy.
I've got to add that this model has had a somewhat rough past - with all my absent-mindedness, I had originally set year as the primary key, which quickly failed as soon as I added two Assignments to different employees. Maybe I should look at the DB schema and see if anything's wrong. Thankfully, the app hasn't made it to production yet, but hopefully this can be fixed without a full DB reset.
If you had created 90 previous records then deleted the rows from your database; your database key index will still be set to what would have been the next primary key number in your database.
The way to resolve this would be to as described in this other stackoverflow post:
SQLite Reset Primary Key Field