I have two picklists in DOM, first is populated during loading of URL when a method in views loads the page. Second picklist's content depends on what user selects in first picklist. How do I bind python method to event when user makes a selection in first picklist, make some manipulations in python, return a list of vallues I'd like to be displayed in the second picklist and then populate it without refreshing the page?
My template looks like this:
{% block content %}
{% if list_of_events %}
<form>
<select>
{% for event in list_of_events %}
<option value="name">{{ event.module }}</option>
{% endfor %}
</select>
</form>
{% else %}
<p>No events available now.</p>
{% endif %}
Next condition is waiting for first_selection argument which should be returned to template after user selects a value in first picklist.
{% if first_selection %}
<form>
<select>
{% for room in list_of_rooms %}
<option value="name">{{ room.id }}</option>
{% endfor %}
</select>
</form>
{% endif %}
<input type="submit" value="Submit">
{% endblock %}
My views.py
method looks like this:
def events(request):
try:
list_of_events = Event.objects.all()
except:
raise Http404('Something\'s wrong with events page loader')
return render(request, 'web_service/schedule.html', {
'list_of_events': list_of_events
})
You can render all the possible second picklist with a display = none then you can add a javascript like:
https://codepen.io/metrafull2/pen/WEgWLo try here
I had a similar issue to OP (the accepted answer is the closest I can find to what I came up), and this was the top hit to my google search, so I'll share what I came up with.
The main difference is I set the
dataType
to 'html' and just appended the rendered template directly to the element. (if you didnt change thedataType
you'd end up with exceptions--wouldn't work in the manner I've implemented)Note: I'm not sure if this is considered best practice
Note: only tested on Django 2.2 and Python 3.6.x
In Django, at least now, there's no direct way to dynamically call
python
method fromhtml
template without refreshing the page.To call
python
method and see it's effect in template without refreshing the page you'll need a bit ofJS
, dedicatedurl
pattern and aview
. It’s not as simple as calling instance method, but not as hard as it may seem.The example below is a demonstration how to respond to a button
click
, send some data to aview
and return the result to template without refreshingDOM
.The only way to call python code from template is relate to in the same way as we relate to
url
, this means we have to create newurl pattern
. Then call necessaryview
and return response to template asJsonResponse
.Note: make sure to import
jquery
at the inside bottom of your<body>
tag.First of all we need to create responder which will handle button click and create
AJAX
request to url connected toview
.AJAX request
passesinput
as parameter to our url pattern, meaning this parameter will be passed to djangoview
. If something returns from our call toview
then data is being unpacked insuccess
closure.Let’s say our template looks like this:
Script handling clicks and request looks like this:
New pattern is needed in urls.py:
Note: the
ajax/
part of url and path of url pattern itself has no influence on how this call is handled. It can be anything you want, for example:^foo/bar/$
.Last step is adding responding Django
view
. This simple example returns the input with some additional text, but generally this is the place where you can call other python methods and do whatever you want: