问题
First I have searched and seen another answer, but it doesn't address my need.
I am trying to POST data using jQuery/AJAX from my HTML to update a list that is also on my HTML.
When I first rendered my template, it had two list-group containers of which the left container is pre populated.
two containers
The choice made user makes on the left container determines the list group data of the right container.
I wanted to send back to the backend Python (server) which selection the user made from the left container, so that I may populate the appropriate list for the second (right) container. This is why I used the POST method using jQuery/AJAX to send users selection.
HTML
Here is a Plnkr of the HTML
Below is the jQuery/AJAX implementation which WORKS. It sends data back to Python (to my views.py):
JS/jQuery/AJAX:
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
$("#leftContainer > a").click(function(event){
event.preventDefault();
$("#leftContainer > a").removeClass("active");
$(this).addClass("active");
var leftDataSet = parseInt($(this).attr("data-set"));
var item_selected = $(this).text();
var item_index = $(this).attr("id") //Users selection to send
$.ajax({
type:'POST',
url:"home/view_results/onclick/",
data:{
selected_item:item_index,
csrfmiddlewaretoken:"{{ csrf_token }}"
},
dataType:"text",
success: function(){$('#message').html("<h3>Data Submitted!</h3>") }
})
});
$("#rightContainer > a").click(function(event){
event.preventDefault();
$(this).toggleClass("active");
});
</script>
views.py
#app/views.py
from django.shortcuts import render
class View_Items():
def render_view_items(self, request, shopid):
item_history = self.get_item_list(shopid) #Fetches a list
return render(request, 'view_results/View_items.html',{
'item_list':item_history,
})
urls.py
#app/urls.py
from django.urls import path, re_path
from . import views
results = views.View_Items()
urlpatterns=[
...
re_path(r'view_results/(?P<shopid>\w+)$', results.render_view_items, name = 'view_items'),
re_path(r'view_results/onclick/$', results.render_view_items_again, name = 'view_results_new'), # NEW
]
My question is:,
now that I have the AJAX data returned back to my Python backend at views.py, do I have to re-render my page to populate the Right container's list group items in my HTML? Or is it possible to update the list without having to re-render. If so, why is my proposed re-render function below NOT updating the RIGHT container of my HTML? Updating the Right container is the objective which required the selection choice of left container.
Addition I made to views.py
#app/views.py
def render_view_items_again(self, request):
selected_item_by_user = request.POST.get('selected_item')
# print(selected_item_by_user)
models = self.get_all_models(selected_item_by_user) #Fetches a list.
# print(models) #Tested if my list is populated.
return render(request, 'view_results/View_items.html',{
'model_list':models,
})
回答1:
It is totally possible to fill the right container, without having to reload your page.
What is usually done is to divide the function from views.py into the case of the first render and when you return from an AJAX POST. In your case, the views.py will be something like:
if request.method == 'POST': # Returning from AJAX
selected_item_by_user = request.POST.get('selected_item')
models = self.get_all_models(selected_item_by_user) #Fetches a list.
return JsonResponse({'completed': "ok", 'list': models})
else: # First time render
item_history = self.get_item_list(shopid) #Fetches a list
return render(request, 'view_results/View_items.html',{
'item_list':item_history,
})
As you can see, I have only rendered the template the first time. When you get back from AJAX, I only call JsonResponse
. Add the following import to your code:
from django.http import JsonResponse
Please be aware that depending on how is built your list (you have not provided the details), you will need to encode it accodingly.
Then, in the success
function of your AJAX method, you can easily use the list
(adapt it so that you fill the right container):
success: function(data){console.log(data.list)}
Hence, the right container will be filled without doing a re-render/refresh of the page.
Edit 1
Now I see that you are also redirecting to a different url in your AJAX method. If you want not to refresh, set your url in the AJAX method as follows:
$.ajax({
type:'POST',
url: window.location.href,
data:{
selected_item:item_index,
csrfmiddlewaretoken:"{{ csrf_token }}"
},
dataType:"text",
success: function(){$('#message').html("<h3>Data Submitted!</h3>") }
})
So you only need one url in the urls.py
file too.
I do not know the HTML code of your right container, but if it is a list ul
(let's suppose that it has an id=list_conditions
), you could add an item to the right container as follows:
// Get where I should add the index
let ul=document.getElementById("list_conditions");
// Create a new child
let li=document.createElement("li");
li.setAttribute("class", "list-group-item list-group-item-secondary");
li.appendChild(document.createTextNode(data.list[0])); // Here you can replace by the index you need from the list
ul.appendChild(li);
来源:https://stackoverflow.com/questions/53561723/do-i-have-to-re-render-my-page-after-updating-template-data