django model field: Why default value not working? - django

When I create a new row in my PG commander
I let small_price empty because I thought I set a default : 0
small_price = models.IntegerField(default=0)
But when I saved It has an alert :
Reason: null value in column "small_price" violates not-null constraint
Why the default not work??
Do I still need to type 0 when create row??

If you are auto-generating your migrations then you need to make a small edit to the migration before you actually apply it. Go into the generated migration and look for the argument: keep_default=False
in the db.add_column call.
You have to change it to: keep_default=True
This way Django will apply your default value to the actual schema + any existing rows.

Related

How to do migratiobn in django?

Initially I migrated one app models after that I added one field there
pol_id = CharField(max_length=25, unique=True)
now if I am running makemigrations its showing me
You are trying to add a non-nullable field 'pol_id' to Health 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
In my db there is no any object, I saw many answer to put there null=True, but I can't add null=True in pol_id, is there any hard migration command to fix this issue?
It comes out because you didn't specify default in the field. You don't have to be surprised at all.
If you don't need to specify default for the field in models.py, just select option number 1, and input '' as the default value.

Django and south migration: unexpected field came out

I'm using Django 1.6 as a banckend and I'm using South for migration.
I have two tables, Content and Channel, I added a field adress in Channel:
class Channel(models.Model):
name = models.CharField(max_length=256)
adress = models.CharField(max_length=256,null=True)
and I added a ForeignKey in table Content:
class Content(models.Model):
name = models.CharField(max_length=256)
channel = models.ForeignKey(Channel, null=True, blank=True)
When I run the command :
python manage.py schemamigration myapp --auto
I got this:
+ Added field adress on myapp.Channel
? The field 'Content.adress' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now.
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception; you can edit the migration to fix it later
? Please select a choice: Connection to v-atm-t3v closed by remote host.
Why do I have field Content.adress? I marked the ForeignKey as null=True,blank=True because I want it to be blank by default, how can I solve that? Thanks!
The message is basically saying: You were having a field called adress in model Content before, and it's couldn't be null when you defined it(you don't have null=True on that field). When you delete it, south needs to know what value do you want to fill in when you recover the field in case you want to reverse the migration.
If you understand south, it has forward and backward methods, to apply and revert the changes respectively. When you want to undo the migration, your data for field adress on model Content cannot be recovered. But you already made it not nullable, south needs to fill in some value, hence the prompt message.
The solution depends on your need. If you don't bother recovering the values for that field, pick 3 would be OK, because you will never run backwards migration. Or pick 2 but it doesn't do any better than 3, just fill in a default value for all records, which is most likely not what you want.

how django knows to update or insert

I'm reading django doc and see how django knows to do the update or insert method when calling save(). The doc says:
If the object’s primary key attribute is set to a value that evaluates to True (i.e. a value other than None or the empty string), Django executes an UPDATE.
If the object’s primary key attribute is not set or if the UPDATE didn’t update anything, Django executes an INSERT link.
But in practice, when I create a new instance of a Model and set its "id" property to a value that already exist in my database records. For example: I have a Model class named "User" and have a propery named "name".Just like below:
class User(model.Model):
name=model.CharField(max_length=100)
Then I create a new User and save it:
user = User(name="xxx")
user.save()
now in my database table, a record like id=1, name="xxx" exists.
Then I create a new User and just set the propery id=1:
newuser = User(id=1)
newuser.save()
not like the doc says.when I had this down.I checked out two records in my database table.One is id = 1 ,another is id=2
So, can anyone explain this to me? I'm confused.Thanks!
Because in newer version of django ( 1.5 > ), django does not check whether the id is in the database or not. So this could depend on the database. If the database report that this is duplicate, then it will update and if the database does not report it then it will insert. Check the doc -
In Django 1.5 and earlier, Django did a SELECT when the primary key
attribute was set. If the SELECT found a row, then Django did an
UPDATE, otherwise it did an INSERT. The old algorithm results in one
more query in the UPDATE case. There are some rare cases where the
database doesn’t report that a row was updated even if the database
contains a row for the object’s primary key value. An example is the
PostgreSQL ON UPDATE trigger which returns NULL. In such cases it is
possible to revert to the old algorithm by setting the select_on_save
option to True.
https://docs.djangoproject.com/en/1.8/ref/models/instances/#how-django-knows-to-update-vs-insert
But if you want this behavior, set select_on_save option to True.
You might wanna try force_update if that is required -
https://docs.djangoproject.com/en/1.8/ref/models/instances/#forcing-an-insert-or-update

How to deal with the required value which does not have a default value in Django model

The version of my Django is 1.7.
I have a model named Booking, it has a Boolean field named is_departure, which is used to describe the booking is departure or arrival.
class Booking(models.Model):
...
is_departure = models.BooleanField()
...
When I migrate my app, it will return me a warning that is_departure does not have a default value.
However, I do not want to add a default value for is_departure. This is a required value and it needs to be filled by user. I do not want to use NullBooleanField neither, because is_departure should not be null.
Is there any good way to remove this warning?
The problem is, what will Django put as a value for all the existing rows that now have a is_departure value that according to you, cannot be null, you can't satisfy this constraint.
If you're still developing, then you can reset the DB and you can indeed use BooleanField without default (since there will be no existing rows violating this)
Otherwise, I'd make the migration put a is_departure value (true or false) on the existing rows, consistent with your business logic

What's the point of 'default=True' in BooleanField

I have a simple question: in my model, I am defining the structure for one of my tables; however, I want to set up a default value for the Booleanfield: own, but it does not seem to be working properly. Here is my code in the model:
class Books(models.Model):
title = models.CharField(max_length=100)
own = models.BooleanField(default=True)
When I desc my table in mysql, this is what I get (note that own has default Null):
Also, when I try to do the following:
INSERT INTO `counters_books` (`title`) VALUES ('My Brain is Open')
I get this error:
ERROR 1364 (HY000): Field 'own' doesn't have a default value
P.S. I understand that by using NullBooleanField I will be able to solve the problem; however, what's the point of default if I cannot insert a row unless I had to specify a value for that field?
default is not handled at the SQL level - it's handled at the model level. Thus, a raw SQL query in your db environment would throw an error. Try this in your Django environment:
>> book_obj = Book('Harry Potter')
>> book_obj.save()
When done at the model level, the default value will be inserted into your SQL DB