Reputation: 809
I've spent the past couple days going over a handful of "Django/AJAX tutorials", but I'm very much a beginner using either AJAX or JQuery (the library I decided to use in my AJAX implementation, I'm open to using something else if it makes sense too).
I'd like to do some of my database updates asynchronously, so I don't need to reload the entire page each time, but due to the dynamic nature of most of my forms, I haven't seen an "easy" way to do this without writing a fair amount of new code. I'm curious if there's an easier way to do what I'm trying to accomplish, without having to write so much new code.
My original app is completely static, meaning anytime I post any data the entire view needs to reload. On the plus side, it's easy for me to determine if I want to reveal/hide certain elements of a form, since I'm basically rebuilding everything on post anyway. A classic example for my app: The user changes the value on a drop-down list, my form reloads and based on the chosen value new fields will be revealed or hidden:
def example_view(request):
if "dropdown_selection" in request.GET:
dropdown_value = request.GET['dropdown_selection'])
# more code to save dropdown_value to my database
.....
# way later on in the same view
if dropdown_value == SHOW_EXTRA_STUFF:
# code to add a bunch of extra elements to a form
For better or for worse, I've got TONS of logic in my views like this, to determine which elements to show/hide based on values which are stored in the database (typically from reading incoming Post data beforehand and saving it off to the database first). So now I want to start doing things a bit more asynchronously :-)
I've managed to hook up a simple drop-down box to update my database via AJAX, with some simple code in my template:
$(document).ready(function() {
$('#{{dropdown_id}}').change(function() {
var dropdown_data = $('#{{dropdown_id}}');
var data = {}
data["{{dropdown_id}}"] = dropdown_data.val();
var args = { type:"GET",
url:"submit/", data:data };
$.ajax(args);
})
});
And I've updated my urls.py to redirect that particular url to another view, which will store the new dropbox value in my database. That part works great, but of course I've got all this logic in my original view which is no longer valid as that dropdown value has changed behind the scenes. Once I force a page-refresh, everything updates correctly to reflect the new value. I'm wondering if there's a simple way I can still use the existing logic (ie show this form or hide that form) without having to write a bunch of Jquery code in my template, which I'm guessing would need to access all those elements directly and require a bunch of new logic. It's almost like I want to re-do exactly what was in my original view, minus the logic that updates database values, rebuilding all the html code, but without actually doing a full page refresh. Maybe it's just wishful thinking :-/
UPDATE - My Solution
As a followup, I've got this working after following Ignacio's suggestion. I'm able to use my existing views/logic and add a minimal amount of extra code to get full AJAX updates. Here's the process I do to convert my static pages to dynamic pages:
Create a new "base" page, that looks something like this:
{% block content %}
<div id="dynamic_data">
</div>
<script>
$(document).ready(function() {
$('#dynamic_data').load('submit/');
$('#dynamic_data').change(function() {
$('#criteria_table').load('submit/');
});
});
</script>
{% endblock content %}
Create a new view, which you will need to update your urls.py to call, based on having "submit" in the url. This view simply calls the original view, with an extra parameter:
def new_view(request):
return original_view(request, repost=True)
Update my original view to have the "repost" parameter. Everything else stays the same, except at the end I change which template it returns:
def original_view(request, repost=False):
# all my database updates, dynamic form generation, etc
# everything stays the same
...
if repost == True:
return render_to_response("myapp/new_table.html",
context,
context_instance=RequestContext(request))
else:
return render_to_response("myapp/base.html",
context,
context_instance=RequestContext(request))
Going back, my "base.html" is the simple template I posted above. My "new_table" template is my original template which generated all the dynamic data. So all I've done is moved my original template somewhere else, created a new view that executes that template, and I use the results of that to re-post data to the div.
Thanks again Ignacio
Upvotes: 0
Views: 970
Reputation: 799200
Shard your templates into logical pieces which you can implement via template tags. You can then wrap the functions the template tags delegate to in view functions and invoke those via AJAX, replacing into the appropriate <div>
s in the page.
Upvotes: 1