I know as per the documentation the following fields do not take allow_blank=True and allow_null=True
BooleanField()
IntegerField()
I need to allow the client to not specify g or d (as per below) and to store the value in the DB as None.
g = serializers.BooleanField()
d = serializers.IntegerField()
Any ideas ?
The different options for handling of empty, blank and null fields are (necessarily) a little subtle, so its unsurprising that it sometimes trips folks up.
I know as per the documentation the following fields do not take allow_blank=True and allow_null=True
That's incorrect:
IntegerField(allow_null=True) is valid.
If you want to allow null inputs for boolean fields you need to use the NullBooleanField() class.
You are correct that neither of them take allow_blank, as the empty string isn't going to be a valid value in either case.
I need to allow the client to not specify g or d (as per below) and to store the value in the DB as None.
You can either use IntegerField(default=None) and NullBooleanField(default=None).
In this case when the values are omitted they will be included as None in serializer.validated_data. You'll want to make sure you use null=True/NullBooleanField on the model field.
Or IntegerField(required=False) and NullBooleanField(required=False).
In this case when the values are omitted they will not be included in serializer.validated_data, and the model field default will be used. You'll want to make sure you use default=None and null=True/NullBooleanField on the model field.
Note that there was a bug when using the Browsable API that empty fields in HTML input did not get the default values set. This is resolved in the upcoming 3.1.4 release.
The initial argument suggested in Edwin's answer can also be useful, but is for setting an value to be initially rendered in HTML form fields.
Django Rest Framework Serializer has initial options to set the dafault value of a field.
g = serializers.BooleanField(initial=True)
d = serializers.IntegerField(initial=0)
http://www.django-rest-framework.org/api-guide/fields/
Related
In my Django application, I am using bulk_create(). For one of the fields in a target model I have assigned a set of validators to restrict the allowed value to uppercase letters (alphabets) and to a fixed length of "3", as shown below:
class Plant(models.Model):
plant = models.CharField(primary_key=True, max_length=4, ...
plant_name = models.CharField(max_length=75, ...
plant_short_name = models.CharField(max_length=3, validators=[...
# rest of the fields ...
I am restricting field plant_short_name to something like CHT for say, Plant Charlotte.
Using the source file (.csv) I am able to successfully create new instances using bulk_create, however I find that the data get saved even with field plant_short_name's value being different.
For example, if I use the source as:
plant,plant_name,plant_short_name
9999,XYZ Plant,XY
the new instance still gets created although the length of (string) value of field plant_short_name is only 2 (instead of 3 as defined in the validators).
If I am to use an online create function (say, Django CreateView), the validators work as expected.
How do I control / rstrict the creation of model instance when a field value of incorrect length is used in the source file?
bulk_create():
This method inserts the provided list of objects into the database in
an efficient manner (generally only 1 query, no matter how many
objects there are). Also, does not call save() on each of the
instances, do not send any pre/post_save signals.
By efficient manner it means there is no validation. You can explore more of the function code in django/models/db/query.py inside the environment.
I'm trying to set the default value for a Date field to a future date with respect to today. However, it gives me the following warning when I set it as below.
return_date = models.DateField(default=(timezone.now() + timedelta(days=1)))
booking.Booking.return_date: (fields.W161) Fixed default value provided.
HINT: It seems you set a fixed date / time / datetime value as default for
this field. This may not be what you want. If you want to have the
current date as default, use `django.utils.timezone.now`
Same warning with the following code.
return_date = models.DateField(default=(date.today() + timedelta(days=1)))
What is the correct way to do this?
Thanks.
You are giving it a fixed time(cause you are calling the timezone.now() so its returned value will be the default) you should pass the function to the default without calling it, like this
def return_date_time():
now = timezone.now()
return now + timedelta(days=1)
and in your field:
return_date = models.DateField(default=return_date_time)
### dont call it, so it will be evaluated by djanog when creating an instance
Try using datetime.date instead of adding to timezone.now
Here is an excerpt from django docs
DateField
class DateField(auto_now=False, auto_now_add=False, **options)
A date, represented in Python by a datetime.date instance. Has a few extra, optional arguments:
DateField.auto_now
Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. Note that the current date is always used; it’s not just a default value that you can override.
The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that.
DateField.auto_now_add
Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it’s not just a default value that you can override. So even if you set a value for this field when creating the object, it will be ignored. If you want to be able to modify this field, set the following instead of auto_now_add=True:
For DateField: default=date.today - from datetime.date.today()
For DateTimeField: default=timezone.now - from django.utils.timezone.now()
The default form widget for this field is a TextInput. The admin adds a JavaScript calendar, and a shortcut for “Today”. Includes an additional invalid_date error message key.
The options auto_now_add, auto_now, and default are mutually exclusive. Any combination of these options will result in an error.
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
I need to store matches in my database and those matches already have a unique ID where they come from. For further assistance and referring, it is best for me to keep this ID:
match = Match(id=my8digitsid)
match.save()
However, incoming matches (not played yet) don't have an ID yet. Can I safely save my match as follow:
match = Match()
match.save
And then, once the match played modify it as such:
match.id = my8digitsid
When I say safely, I mean whether or not that the default ID generated (auto-incremented I guess) is unique and won't have any conflicts with my self-made IDs.
Yes, you can be sure that the ORM will make unique id's as referred in the documentation here. The database is the one calculating the new number.
If a model has an AutoField — an auto-incrementing primary key — then
that auto-incremented value will be calculated and saved as an
attribute on your object the first time you call save():
>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id # Returns None, because b doesn't have an ID yet.
>>> b2.save()
>>> b2.id # Returns the ID of your new object. There’s no way to tell what the value of an ID will be before you call save(), because
that value is calculated by your database, not by Django.
For convenience, each model has an AutoField named id by default
unless you explicitly specify primary_key=True on a field in your
model.
You can also provide the Id if you want using this. I copy below the info from Django documentation.
Explicitly specifying auto-primary-key values If a model has an
AutoField but you want to define a new object’s ID explicitly when
saving, just define it explicitly before saving, rather than relying
on the auto-assignment of the ID:
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id # Returns 3.
>>> b3.save()
>>> b3.id # Returns 3.
If you assign auto-primary-key values manually, make sure not to use
an already-existing primary-key value! If you create a new object with
an explicit primary-key value that already exists in the database,
Django will assume you’re changing the existing record rather than
creating a new one.
Given the above 'Cheddar Talk' blog example, this example would
override the previous record in the database:
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save() # Overrides the previous blog with ID=3!
But I don't recommend You to assign that ID yourself. I think more convenient to create a field of the model with the ID from where they come from.
The reason Why I don't recommend this is because you will have to verify always that the id provided has not been used before before inserting it. As a general rule I try to avoid modifying the standard behaviour of Django as much as possible.
I have two models as
class Employer(models.Model):
..
..
class JobTitle(models.Model):
type = models.IntegerField(null=False, choices=JobTitles.CHOICES,blank=True,default=0)
employer = models.OneToOneField(Employer,unique=True,null=False)
I have defined admin for Employer and defined JobTitle as inline class.
However, when I saved an Employer object without selecting JobTitle, it raises the error invalid literal for int() with base 10: '' due to the type field of JobTitle.
I would like to set type to 0, as I defined default=0, if I don't select any jobtitle when employer is saved.
How can I achieve this ?
So, I'm inferring this from the code you posted, but I think that you're mixing strategies here. I assume based on the way you've constructed your question that you want to me able to make a job title with no type. Alternatively, you want one job type to be the default selection. I further infer, although now I'm stretching a bit, that you have a custom "No Type" choice (you didn't show us your JobTitles.CHOICES tuple so I have to guess) that corresponds to the 0 value that you've set as the default.
If you want to have a default job type (even if you're calling it "No Job Type" or something similar), then you should set it using the default keyword argument (as you have done) and you should set null=False and blank=False (alternatively, omit both, as these are the default values).
However, if you want it to be possible that there is a job title with no type, then unless you have some reason in your implementation to do something else, the purest way to represent this in data is to use the null SQL value. If you want to go that route, the correct way to do it is to set blank=True and null=True, and then either set default=None or omit that keyword argument entirely.
That should get you the behavior that you seek.
For Model arguments, default is used when Django save your data to Database...
On the other hand, your error occurs during data parsing. When you submit your form, django parses data to relevant type if needed. When your html form is submitted, django recieves string data like
{'title':'12', 'employer_id':'23'...}
So, django have to parse type into ineger before it save it to the database... Since your forms sends a nullstring '' , int('') simply fails with TypeError.
What you must do is removing blank=True. Or somehow you must override the default behaviour of combobox default value and set it 0 instead of ''.