django-bootstrap-datepicker-plus icon indicating copy to clipboard operation
django-bootstrap-datepicker-plus copied to clipboard

Possible bug: options={'maxDate': foo} changing the initial/default value for field

Open GCru opened this issue 5 years ago • 3 comments

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

GCru avatar May 02 '19 20:05 GCru

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')
            },
        )

adremides avatar Feb 20 '21 18:02 adremides

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.

adremides avatar Mar 05 '21 22:03 adremides

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', })

rez0n avatar Apr 04 '21 12:04 rez0n