ModelChoiceField: remove empty option and select default value - django

I'm using the default form field for a models.ForeignKey field, which is a ModelChoiceField using the Select widget.
The related model in question is a Weekday, and the field was made nullable so that it didn't force a default value on hundreds of existing entries. However, in practice, our default should be Sunday, which is Weekday.objects.get(day_of_week=6).
By default the select widget for a nullable field when rendered displays the null option. How can I discard this option and have a default value instead?
If I set a initial value, that one is selected by default on a new form:
self.fields['start_weekday'].initial = Weekday.objects.get(day_of_week=6)
But the empty value is still listed. I tried overriding the widget choices:
self.fields['start_weekday'].widget.choices = [(wd.day_of_week, wd.name) for wd in Weekday.objects.all()]
However now Sunday isn't selected by default. I thought maybe I need to use the option value as the initial one but that didn't work either:
self.fields['start_weekday'].initial = Weekday.objects.get(day_of_week=6).pk
In short: how can I remove the empty option in a nullable model field and select a default instead?

Provide empty_label=None in ModelChoiceField
start_weekday = ModelChoiceField(Weekday.objects.filter(day_of_week=6), empty_label=None)
OR
instead of assigning initial, you can assign empty_label also
self.fields['start_weekday'].empty_label = None
OR
you can provide default value in field in models also
start_weekday = models.CharField(max_length=10,choices=[(wd.day_of_week, wd.name) for wd in Weekday.objects.all()],default=6)

Related

What's the default value for a DecimalField in Django?

I'm adding a new DecimalField to my model, what value will it have by default in the database (if I don't specify the default explicitly on the field e.g. default=1.23)?
amount = models.DecimalField(max_digits=15, decimal_places=3)
I'm expecting it will be either NULL or 0.0 (or None or Decimal(0.000) in python), but which?
Couldn't find this mentioned in the docs: https://docs.djangoproject.com/en/2.2/ref/models/fields/#decimalfield
I'm using Django 2.2, but expect this is consistent across versions.
Django does not set any default values. You must specify the default value yourself.
amount = models.DecimalField(max_digits=15, decimal_places=3, default=0.0)
Based upon your definition. The default value would be 0.000
If you had keyword argument null=True then you may expect NULL where a value has not been entered in.
Clearly the default value should be NULL but it will happen only when you activate it i.e. by setting null = True as one of the attributes to the model field. I haven't checked it recently though.
However, I recommend setting default value by yourself. e.g. default = 0.000.
Alternatively, you need to pass another attribute similar to blank = True or required = False if you want the model field to be an optional field. Otherwise, it will always prompt you to fill some decimal value in it.

How to set Django model date field default value to future date?

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.

Storing Default Values for BooleanField() and IntegerField() in Django REST

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/

django south - unique=True, but "give default value for existing rows" ?

I have created an index field
channel_indexid = PositiveIntegerField(db_index=True, unique=True)
If I try to migrate, south is asking me to enter default value for existing rows.
1. Quit now, and add a default...
2. Specify a one-off value..
But, channel_indexid is a unique, how can I give one default value for all rows? is there any workound for this. this is really annoying
Since you are modifying a model, South will ask you for default value for existing rows since your new field, by default is null=False. You can avoid to give it a default value by setting null=True, blank=True.
If you don't want it to be nullable and you still want to add this field as not nullable, then you have to drop the table and create it again with your new field.
South by default give new columns a null value but since by default fields are null=False then South ask you for a value to give to the new field. South does not give empty strings or 0 as default values for string or integer fields, you have to tell South the default value if the field is not nullable, and if it is nullable it will give a default value of null.

Django Autoselect Foreign Key Value

I have a model that contains a foreign key value, then in the form generated from this model, I want to auto select the record's key according to the record I'm adding the form's contents to...I've tried the below code, but it tells me QuerySet doesn't contain vehicle
stock = Issues.objects.filter(vehicle=id)
form = IssuesForm(initial={'id_vehicle': stock.vehicle})
I'm a bit new to django btw so any ideas are highly appreciated
filter always gives a QuerySet, which is a set of values. If you just want a single object, you should use get.
However I don't really understand why you need to do the lookup at all. You have the id value already, since you are using it to look up stock. So why don't you just pass id as the value for id_vehicle?