Issue
I have a Django form where the user can select a variable in a choice field, start date and end date in a select date widget. For different variables, the possible start and end dates varies. The form works, but only with one pre-defined date range for all variables. How can I change the possible start and end dates according to the variable?
from django import forms
from datetime import datetime
Parameter_CHOICES = [
('', 'Wähle ein Umweltvariable'),
('niederschlag', 'Niederschlag [L/m²]'),
('bodentemperatur_5cm', 'Bodentemperatur in 5cm Tiefe [°C]')
]
class DataForm(forms.Form):
parameter = forms.ChoiceField(
widget=forms.Select,
choices=Parameter_CHOICES)
start_date = forms.DateField(label='Beginn:', widget=forms.SelectDateWidget(years=list(range(2007,2023))))
end_date = forms.DateField(label='Ende:', initial=datetime.now, widget=forms.SelectDateWidget(years=list(range(2007,2023))))
What i need is to set the
years=list(range(2007,2023))
for niederschlag
and for bodentemperatur_5cm to
years=list(range(1991,2023))
Is it possible to do this in the forms.py or do I have to make this in javascript/html?
Update I try to solve it with jQuery, but I stuck. I try to change the Years Range choicec according to parameter with this function:
$("#id_parameter").on('change', function(){
var parameter = $("#id_parameter").val();
if (parameter == 'niederschlag') {
$("#id_start_date_year").val(2007);
}
if (parameter == 'bodentemperatur_5cm') {
$("#id_start_date_year").val(1991);
}
But this only change the value the user can see first. How can I change the possible years or range after the user select the parameter with jQuery?
Solution
There are 2 solutions to this that I can think of:
With views
First create the forms, the first that lets you choose the type, the second initiates the form for the options you make in "get_first_and_second_year":
# forms
class DataForm(forms.Form):
Parameter_CHOICES = [
('', 'Wähle ein Umweltvariable'),
('niederschlag', 'Niederschlag [L/m²]'),
('bodentemperatur_5cm', 'Bodentemperatur in 5cm Tiefe [°C]')
]
parameter = forms.ChoiceField(
widget = forms.Select,
choices = Parameter_CHOICES
)
class DatePickForm(forms.Form):
start_date = forms.DateField(label='Beginn:', widget=forms.SelectDateWidget())
end_date = forms.DateField(label='Ende:', initial=datetime.now, widget=forms.SelectDateWidget())
def __init__(self, *args, **kwargs):
# get kwargs
first_year = kwargs.pop('first_year', None)
second_year = kwargs.pop('second_year', None)
# super
super(DatePickForm, self).__init__(*args, **kwargs)
# initialize form fields
self.fields['start_date'] = forms.DateField(
label='Beginn:',
widget=forms.SelectDateWidget(
years=list(range(first_year,second_year))
)
)
self.fields['end_date'] = forms.DateField(
label='Ende:',
widget=forms.SelectDateWidget(
years=list(range(first_year,second_year))
)
)
Make the call for the page using different views:
# call in views
@login_required(login_url="/login/")
def date_form_view(request):
form = DataForm(request.POST or None)
if request.method == 'POST':
#................................................................
# treat form
#................................................................
redirect('date_pick', form_choice=form_choice)
# render with context
context = {'form': form}
render(request, "", context)
def get_first_and_second_year(form_choice):
# return first and second year depending on form choice
match form_choice:
case 'niederschlag':
return first_year, second_year
case 'bodentemperatur_5cm':
return first_year, second_year
case _:
return 0, 0
@login_required(login_url="/login/")
def date_form_view(request, form_choice):
# dont forget to map url to this view with the argument
first_year, second_year = get_first_and_second_year(form_choice)
form = DatePickForm(request.POST or None, first_year=first_year, second_year=second_year)
if request.method == 'POST':
#................................................................
# treat form
#................................................................
start_date = request.POST.get('start_date')
# ...
context = {'form': form}
render(request, "", context)
With ajax (smoother interface, harder to code):
Ajax post/get calls explanation https://www.pluralsight.com/guides/work-with-ajax-django
Pass a json string to to the view that describes the different actions for each form_choice:
And prepend the html with the form for the form_choice.
Answered By - Ramon G.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.