How to set default value for FloatField in django model - python

How can I set a default value for FloatField in django.
Initially when I had created the model and declared the float field as:
cost = models.FloatField(null=True, blank=True)
and db also created successfully through south migration.
But now when I am trying to do edit on that field using the html form, and no value is entered in the cost field, in the form its throwing value error.
Thus I think if I can set a default value for cost field it may fix the problem.
But I don't know how to set a default value for FloatField in django.

Your code should work. Perhaps something is setting the empty value to a non-null value (like an empty string). I'd have to see the full error message.
Since this is an old thread, I'm going to post the answer to the question I came here for, "How do you set FloatField default to Null in the database?"
cost = models.FloatField(null=True, blank=True, default=None)

Float Field is quite related to Decimal Field so, probably it should take a default argument. Try doing this..
cost = models.FloatField(default=to_some_value)

Related

What do I set the default value as when adding a field to a model?

I added the field user which is a foreign key to another model called User. This field was added to the model called Bid. However, when I tried to migrate the changes, I got the message:
It is impossible to add a non-nullable field 'user' to bid without specifying a default. This is because 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 manually define a default value in models.py.
Last time, I set it to 'user' and got an error that stated: ValueError: invalid literal for int() with base 10: 'user'.
What should I set the default value as?
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)
As the error says, you are creating a new field in your table. When creating a new field, existing rows need to be taken into consideration. Safest approach is to set it as null=True and handle the field later.
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
However you may not want a Bid to have a null user. In which case I recommend looking into how to write a custom migration to populate existing rows.
Another note: if the data you have in your table is not needed, you could consider dropping the table and rebuilding it or deleting your migrations and creating them again with manage.py makemigrations - again only if the data you have in your db is not needed.
If you add a relationship via a new foreign key, you have two options
You make the new FK nullable and let it default to NULL (i.e. None in python). This way, legacy entries with unknown relations will have NULL as the FK, i.e. do not know their users.
You manually populate the legacy fields with the appropriate foreign keys to the Bid records. This requires that you have kept that information beforehand.

how to set a string value as a default value of a float field in django models

I couldn't set a string value as the default in a float field in my Django model. Here is my code:
from django.db import models
class Product(models.Model):
Name = models.CharField(max_length=700, null=True)
Price = models.FloatField(null=True)
Screen_size = models.FloatField(max_length=300, blank=True ,default="Not mentioned by the seller" , null=True)
Focus_type = models.CharField(max_length=300, blank=True ,default="Not mentioned by the seller" , null=True)
When I try to run the code I get this error:
ValueError: Field 'Screen_size' expected a number but got 'Not mentioned by the seller'.
This default value will be saved into databases, and easy to understand, a string value can't be saved to a float field --- The database is statically typed.
Normally, if you want to do something like this, your should use property decorator.
class Product(models.Model):
Name = models.CharField(max_length=700, null=True)
Price = models.FloatField(null=True)
Screen_size = models.FloatField(blank=True ,null=True)
Focus_type = models.CharField(max_length=300, blank=True ,default="Not mentioned by the seller" , null=True)
#property
def screen_size(self):
if self.Screen_size is not None:
return self.Screen_size
return "Not mentioned by the seller"
You can't use max_length in FloatField; it's only appliable for text fields such as CharField.
You can't set a string as the default value of a FloatField because FloatField is for numbers. If you want to mark something as "Not specified by the seller", I recommend you simply don't define a default. Since the field is null=True, you can use None whenever you want to mark a screen size as "not specified by the seller"
If you need None for something else, you can use a special value that doesn't make sense for screen sizes such as -1. You can define
SCREEN_SIZE_NOT_SPECIFIED_BY_SELLER = -1
and then
Screen_size = models.FloatField(max_length=300, blank=True ,default=SCREEN_SIZE_NOT_SPECIFIED_BY_SELLER , null=True)
EDIT: Yang HG's answer is good too; but i'd replace Screen_Size with _screen_size if you don't intend to use it (and to avoid two variables with the same name but different capitalization)
I don't know much about Django specifically, but from what I know of general software/database design, I'd guess that it's a bad idea to supply a message as the default value for any field.
Instead, I think the correct approach is to use null=True and blank=True (as you already have) on the float field, allowing "no value" to be represented as null (i.e. None). Then, wherever your model is used, you can replace the null value with whatever message you want (including any special formatting you might want to use to indicate that the value is missing).
For the string field, the documentation recommends against using null=True: for strings, you should just use the empty string to indicate "no value."
One clear benefit to this approach is that there is never a risk that a string field will have a value equal to the default message. What if a seller put in "not mentioned by the seller" as Focus_type? That example sounds silly, but it can be an issue in other cases.
Also, as a general recommendation for Python, the common convention is to use all-lowercase letters and underscores for variable names (like_this) and only capitalize class names (in CamelCase) and constants (in ALL_CAPS). Class fields should generally be capitalized as variables. If you want to learn more about conventional Python style, take a look at PEP 8.

Django (1.9) makemigrations doesn't get Blank=True on boolean field

I have the following model:
class Site(models.Model):
"""
Model for a site entry
#author: Leonardo Pessoa
#since: 05/09/2016
"""
from decimal import Decimal
consolidated_financials = models.BooleanField(blank=True)
type = models.ForeignKey(Type)
tier1_business = models.ForeignKey(Business, limit_choices_to = {'tier': 1}, related_name='%(class)s_tier1')
Note that the consolidated_financials field has now the blank=True statement.
This was newly included. When I ran makemigrations, it didn't get the change, but when I add to finance_manager_sso it worked normally.
Is there a restriction with the Boolean field specifically?
Thanks
BooleanField does not take null=True, instead, use NullBooleanField.
There is a great answer on Programmers.se by Jacob Maristany that explains the reasoning behind this well
By allowing nulls in a boolean field, you are turning an intended binary representation (true/false) into a tri-state representation (true, false, null) where your 'null' entries are indeterminate.
For the full discussion, see Should I store False as Null in a boolean database field?
The blank parameter is not used by BooleanField. Instead, it is hard-coded to True. Passing blank=False has no effect, so the migration autodetector doesn't detect any changes to the field, and doesn't create any migrations.
Since the blank parameter is used by IntegerField, passing in blank=False will lead to a change in the serialized field. The migration autodetector will detect that change and create a migration (even though that change doesn't affect the database).

south migration: "database backend does not accept 0 as a value for AutoField" (mysql)

I'm new to django and trying to have a Foreign key back to users for an assignee and reporter.
But when i'm trying to apply the change with South i get the error
ValueError: The database backend does not accept 0 as a value for AutoField.
My Model Code:
class Ticket(models.Model):
title = models.CharField(max_length=80)
text = models.TextField(blank=True)
prioritys = models.ForeignKey(Prioritys)
ticket_created = models.DateTimeField(auto_now_add=True)
ticket_updated = models.DateTimeField(auto_now=True)
assignee = models.ForeignKey(User, null=True, related_name='assignee')
reporter = models.ForeignKey(User, null=True, related_name='reporter')
def escaped_text(self):
return markdown.markdown(self.text)
def __unicode__(self):
return self.text
If this happens when you run manage.py migrate (or manage.py syncdb in old versions), the reason maybe is that you have tried to add a foreign key to a model which uses AutoField as its primary key, and use 0 as the default value. Edit the migration file and remove the argument default=0 in AddField operations. It works for me in Django 1.10.
I wasn't using South, but I recently upgraded from Django 1.4 to 1.6 (with MySQL as db backend for both), and was getting the same ValueError when trying to save some models. I tracked it down to a field that was a recursive ForeignKey. So I had:
class Foo(models.Model):
...
duplicate = models.ForeignKey('self', blank=True, null=True)
...
Somewhere along the line—unfortunately I'm not sure where—many of my objects had gotten the value of 0 for duplicate_id.
>>> Foo.objects.filter(duplicate_id=0).count()
2078
This didn't occur for any of my other ForeignKey fields, only the self-referential one. So I set the values of that field back to None, and this fixed the error.
>>> Foo.objects.filter(duplicate_id=0).update(duplicate=None)
2078L
Because this particular error doesn't point you to a specific field that's causing problems, in general you can check if a ForeignKey field fieldname has any 0 values:
>>> Foo.objects.filter(fieldname_id=0).count()
If this gives a non-zero result, that field probably needs to be fixed.
A long-long time ago there was a problem with Autofield.
https://code.djangoproject.com/ticket/17653
an interesting quotes:
A:
It seems you are trying to save 0 to a ForeignKey which points to an
AutoField. But, this is illegal, as the AutoField will not accept that
value and so the ForeignKey can not hold that value either.
B:
So this fix creates another problem when you need to be able to accept
a value of 0 (or if you are working on a DB that already has a value
of 0!) in an autofield. In my case, I need to accept an ID of zero so
that my foreign key can point to zero so that a unique constraint can
work properly.
It looks like you have 0 in "user"."user_id".
But again... Full StackTrace, please...
I got the same error after upgrading to django 1.7.1
it was caused when saving a model that had a foreign key to another model that for some reason had an id starting auto increment with 0, i guess this was allowed in previous django versions, but not now.

Wrong validation error on a django modelform field when passed through clean method

Model and ModelForm in django project are defined like this :
class Consumption(models.Model):
date=models.DateTimeField(default=datetime.now)
product_name=models.ForeignKey(Stock,to_field='product_name')
quantity=models.IntegerField()
customer=models.CharField(max_length=50,null=True,blank=True)
def __unicode__(self):
return self.product_name
class ConsumptionForm(ModelForm):
class Meta:
model=Consumption
def clean_quantity(self):
cleaned_data=self.cleaned_data
product=cleaned_data.get("product_name")
quantity=int(cleaned_data.get('quantity'))
stock=Stock.objects.get(product_name=product)
if quantity > stock.quantity:
raise forms.ValidationError("Not enough stock")
return cleaned_data
where Stock class contains product name which serves as Foreign Key to Consumption and and whose quantity should be greater than consumption quantity.
Now the problem is when I enter submit to ConsumptionForm . It gives me error on quantity field as this field must be an integer even after when I am providing it an integer.
What can be the reason of this?
You're returning the whole cleaned_data dictionary from the clean_quantity method, rather than just the value of quantity.
You won't need to typecast cleaned_data.get('quantity') to int. Django's to_python() method on the form base class will do that for you. All forms will try to convert their values to Python values as part of the validation process.
I don't see anything in your clean_quantity() method that would make me think that it won't work, although you're not showing your Stock class so we can see what type of field stock.quantity is.
My advice would be to write a unit test for this form and view method to ensure you're getting the correct values. https://docs.djangoproject.com/en/1.3/topics/testing/
If you're not in a habit of writing unit tests, now is a great time to start. They can really save you a lot of time.

Categories

Resources