django-bootstrap-datepicker-plus
django-bootstrap-datepicker-plus copied to clipboard
Possible bug: options={'maxDate': foo} changing the initial/default value for field
Thank you for the great widget.
I am using the minDate and maxDate options in the widgets. The minDate option works as expected. The maxDate option correctly sets the max date, but then also populates the date field as the initial value or default value every time the form is called, instead of using the value from the initial dictionary passed from Views. When only using the minDate option, the correct initial value from the initial dictionary is set.
I also tried another option by not passing the initial dictionary from Views, but setting the defaultDate under options. As before, this works fine alongside the minDate option but gets overridden by the maxDate option so that the default date shown is maxDate.
See my script below. The initial (default) value of date_y is always set to maxDate.
Note that in both cases I am defining the widgets in form __init__
because I am passing the minDate and maxDate from Views as these will change each time the form is called.
Thank you Gerhard
class DatePickerPlusPage(View):
""" Show a form for entering dates date_x and date_y using
django_bootstrap_datepicker_plus.
date_x range cannot be below date_x_range_min
date_y range cannot be above date_y_range_max
As intial values for these fields use today's date, or if available the previously entered
values
"""
form_class = DatePickerPlusForm
template_name = 'date_picker_plus_page.html'
def get(self, request):
if self.request.GET.get('date_x', default=None) is None:
# first call
initial_form_dict={'date_x':datetime.now().date,'date_y': datetime.now().date}
else:
# calls with form filled in
date_picker_form = self.form_class(data=request.GET)
date_picker_form.is_valid()
date_x = date_picker_form.cleaned_data['date_x']
date_y = date_picker_form.cleaned_data['date_y']
print('This is what the form contains:', date_x, date_y)
initial_form_dict = {'date_x': date_x,'date_y': date_y}
context = {}
context['date_picker_form'] = self.form_class(initial=initial_form_dict,
date_x_range_min=datetime(2000, 1, 1).date(),
date_y_range_max=datetime(2010, 12, 31).date())
template = loader.get_template(self.template_name)
output = template.render(context, request)
return HttpResponse(output)
class DatePickerPlusForm(forms.Form):
date_x = forms.CharField() # needs to be CharField since we are using MonthPicker
date_y = forms.CharField()
def __init__(self, *args, date_x_range_min=None, date_y_range_max=None,**kwargs):
super().__init__(*args, **kwargs)
# convert date_x_range_min to json date
if date_x_range_min is not None:
date_x_range_min = date_x_range_min.strftime('%b %Y')
# convert date_y_range_max to json date
if date_y_range_max is not None:
date_y_range_max = date_y_range_max.strftime('%b %Y')
# set up DatePicker widgets
self.fields['date_x'].widget=MonthPickerInput(format='%b %Y',options={'minDate':
date_x_range_min})
self.fields['date_y'].widget=MonthPickerInput(format='%b %Y',options={'maxDate':
date_y_range_max})
return
def clean_date_x(self):
""" Convert str to date type"""
updated_date = self.cleaned_data['date_x']
updated_date = datetime.strptime('1 ' + updated_date ,'%d %b %Y').date()
return updated_date
def clean_date_y(self):
""" Convert str to date type"""
updated_date = self.cleaned_data['date_y']
updated_date = datetime.strptime('15 ' + updated_date,'%d %b %Y').date()
return updated_date
I encounter this bug too. It seems not working correctly when maxDate is the same day as the actual day. I get around the problem by add 1 to it:
# forms.py
from django import forms
from django.utils import timezone
from dateutil.relativedelta import relativedelta
from .models import SomeModel
from bootstrap_datepicker_plus import DatePickerInput
class SomeModelForm(forms.ModelForm):
class Meta:
model = SomeModel
fields = [
'date'
]
def __init__(self, *args, **kwargs):
super(SomeModelForm, self).__init__(*args, **kwargs)
self.fields['date'].widget = DatePickerInput(
options={
"maxDate": (
timezone.localdate() + relativedelta(days=1)
).strftime('%Y-%m-%d')
},
)
Also I found this today in another issue How to restrict date and time in django bootstrap datetimepicker plus?
Using strftime('%Y-%m-%d 23:59:59')
instead strftime('%Y-%m-%d')
solves the issue too.
Comment for guys who faced with same issue, but with the minDate
.
You need to set initial date value for datepicker this way.
self.fields['min_date_field'].widget = DatePickerInput(
format='%Y-%m-%d', options={'minDate': '2021-01-01', "date": '2021-04-04', })