I have a form displayed in my Django project, and one of the form fields is a DateTimeInput
widget, defined with:
presentation_date = mDateTimeField(required=False, label="Presentation date", widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M'))
This widget currently displays all dates between the start of last year to the end of this year (01/01/2016- 31/12/2017). However, at the end of last year this caused some issues, as it meant that users were unable to select dates for the beginning of this year. What I want to do is extend the range of the dates available for selection in the widget by one year (i.e the new range would be 01/01/2016- 31/12/2018).
I understand that it is possible to do this using form validation (for example, by writing a view such as clean_presentation_date()
and performing the validation inside that view, but this won't solve the issue I'm having- as currently, dates before 01/01/2016 or after 31/12/2017 (displayed in the datetimepicker
calendar that's shown when the user selects the field in the form) are 'greyed out' and it is not possible to select them. This is exactly the functionality that I want, but I just want to change the values of the dates on which it is performed, so that at least the whole of the next calendar year is always selectable.
I have searched for maxDate
& minDate
variables within the forms.py
file where the form with this field is defined, but can't find anything that looks like it is what's restricting which dates are available to be selected, and which are not selectable.
The view
that's showing the page with this form on it is defined with:
def concept(request, project_id):
project = Project.objects.prefetch_related('budget_versions').get(id=project_id)
deposit = Deposit.objects.get_or_create(project=project)[0]
presentations = project.budget_versions.select_related('meeting').prefetch_related('budget_items', 'cci_items', 'presenters').filter(version_number__isnull=False).annotate(vn=F('version_number') * -1).order_by('presentation_date', 'created', '-vn')
end_details = EndDetails.objects.get_or_create(project=project)[0]
presentation_formset = BudgetPresentationFormset(prefix="presentations", instance=project, queryset=presentations)
drawing_formset = DrawingUploadFormset(prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created'))
context = {
'project': project,
'presentations': presentations,
'presentation_formset': presentation_formset,
'drawing_formset': drawing_formset,
'deposit_form': DepositInfoForm(instance=deposit),
'ended_form': EndDetailsForm(instance=end_details),
'budget_notes_form': BudgetNotesForm(instance=project.budget_overview),
}
The particular form
I'm looking at is the presentations
one, defined in forms.py
:
class FirstPresentationForm(ValidatedForm):
""" UNUSED """
who_presenting = forms.CharField()
details = forms.CharField(required=False, label='Original option costed')
presentation_date = mDateTimeField(required=False, label="Presentation date", widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M')) #ERF(19/12/2016 @ 1210) Remove 'datetimepicker' from field..., attrs=({'class':'datetimepicker'})))
class Meta:
model = Budget
fields = ('presentation_date','who_presenting','details')
def __init__(self, *args, **kwargs):
instance = kwargs.get('instance', {})
project = instance.project
who_presenting = [pe.employee.id for pe in project.assigned.select_related('employee').filter(role=Role.P)]
#Make into an array with two employee IDs, or None. If two results were found, they will already be in the right format
if len(who_presenting)==1:
who_presenting.append(None)
elif not who_presenting:
who_presenting = None
if instance.presentation_date:
pres_meeting, created = Meeting.objects.get_or_create(project=project, purpose='6')
self.pres_meeting_id = pres_meeting.id
self.pres_meeting_creator = pres_meeting.event_creator or ''
if created:
pres_meeting.date = instance.presentation_date
pres_meeting.save()
initial = kwargs.get('initial', {})
initial={
'who_presenting': who_presenting,
}
kwargs['initial'] = initial
super(FirstPresentationForm, self).__init__(*args, **kwargs)
self.fields['who_presenting'] = AutoFlexiSelect(model='e', required=False, choices=get_choices('DESIGN_EMPLOYEE_CHOICES'), current_id=who_presenting, label="Who is presenting")
self.fields['presentation_date'].widget.attrs.update({'data-meeting-id': getattr(self,'pres_meeting_id', ''), 'data-meeting-creator': getattr(self,'pres_meeting_creator', '')})
def save(self, commit=True):
project = self.instance.project
data = self.cleaned_data
try: ProjectEmployee.objects.filter(project=project, role=Role.P).delete() #Delete current records, if any, to prevent build up on editing this field
except ObjectDoesNotExist: pass
if data['who_presenting']:
designers = data['who_presenting']
# Get the ids from the form field (received as a string)
designers = [re.sub('\D+', '', s) for s in designers.split(',')]
who_presenting_1 = Employee.objects.get(id=designers[0])
who_presenting_2 = designers[1] #If only one employee in selected choice, this will be None
if who_presenting_2: who_presenting_2 = Employee.objects.get(id=designers[1]) #If two employees in selected choice, sets the second one
pe = ProjectEmployee(project=project, employee=who_presenting_1, role=Role.P)
pe.save()
if who_presenting_2: #If a second designer, delete as well
pe = ProjectEmployee(project=project, employee=who_presenting_2, role=Role.P)
pe.save()
if 'presentation_date' in self.changed_data:
from events.models import refresh_group_cache
print '************'
pres_meeting = Meeting.objects.get(project=project, purpose='6')
self.instance.meeting = pres_meeting
self.instance.save()
print 'Updating date', data['presentation_date'], pres_meeting.id
pres_meeting.date = data['presentation_date']
pres_meeting.save()
refresh_group_cache(pres_meeting.event_creator.calendar_id, pres_meeting.date.year, pres_meeting.date.month, pres_meeting.event_id, pres_meeting)
return super(FirstPresentationForm, self).save(commit=commit)
I have tried passing/ setting max_date
as an attribute of the presentation_date
variable, but it doesn't appear to have an attribute/ property by this name...
How can I specify a particular date as this widget
's maxDate
, so that the user is able to select dates up until December of next year, rather than just up until December of this year?
Edit
The mDateTimeField
that's using the widget
is also defined in forms.py
, with:
class mDateTimeField(forms.DateTimeField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('input_formats', DATE_INPUT_FORMATS)
super(mDateTimeField, self).__init__(*args, **kwargs)
This should help you:
Usage: