Django+Ajax实现无刷新表单提交并展示字符串长度求助
Hi Kiran, let's fix that second part of your functionality—getting the string length without a page refresh. Here's a step-by-step solution tailored to your code:
Step 1: Update View Functions to Return JSON
First, we need to modify your view1 and view2 functions to return JSON data instead of rendering a template when handling POST requests. This way, your Ajax call can receive the length value directly.
Update your views.py:
from django.shortcuts import render from django.http import JsonResponse # Add this import from .forms import Form1, Form2 from .controllers import get_length def home(request): return render(request, 'ajax_demo/home.html') def view1(request): if request.method == "POST": form = Form1(request.POST) if form.is_valid(): selected_name = form.cleaned_data.get('name1') # Get the actual string from the model instance (more reliable than str()) name_str = selected_name.name1 length = get_length(name_str) # Return JSON instead of rendering a template return JsonResponse({'length': length}) else: form = Form1() return render(request, 'ajax_demo/template1.html', {'form': form}) def view2(request): if request.method == "POST": form = Form2(request.POST) if form.is_valid(): selected_name = form.cleaned_data.get('name2') name_str = selected_name.name2 length = get_length(name_str) return JsonResponse({'length': length}) else: form = Form2() return render(request, 'ajax_demo/template2.html', {'form': form})
Step 2: Add Ajax Handling for Form Submission
Since your forms are loaded dynamically via Ajax, we need to use event delegation to listen for the submit event (because the forms don't exist in the initial DOM). Update the JavaScript in home.html:
$(document).ready(function (){ $(function getForm1(){ $("#load_form1").click(function (){ $.ajax({ url: "/view1/", type: "GET", success: function (data){ $("#form_space").html(data); $("#form_space").fadeIn("slow"); // Hide output when switching forms for cleaner UX $("#output_string_length").hide(); } }); }); }); $(function getForm2(){ $("#load_form2").click(function (){ $.ajax({ url: "/view2/", type: "GET", success: function (data){ $("#form_space").html(data); $("#form_space").fadeIn("slow"); $("#output_string_length").hide(); } }); }); }); // Handle Form1 submission (event delegation for dynamic content) $(document).on('submit', '#form1', function(e) { e.preventDefault(); // Stop browser from reloading the page var formData = $(this).serialize(); $.ajax({ url: $(this).attr('action'), type: "POST", data: formData, success: function(response) { // Show and update the output div with the length $("#output_string_length").text(`Selected string length: ${response.length}`).fadeIn("slow"); }, error: function(xhr, status, error) { console.error("Error processing form:", error); } }); }); // Handle Form2 submission $(document).on('submit', '#form2', function(e) { e.preventDefault(); var formData = $(this).serialize(); $.ajax({ url: $(this).attr('action'), type: "POST", data: formData, success: function(response) { $("#output_string_length").text(`Selected string length: ${response.length}`).fadeIn("slow"); }, error: function(xhr, status, error) { console.error("Error processing form:", error); } }); }); });
Key Changes Here:
- Used
$(document).on('submit', '#form1', ...)to listen for submissions on dynamically loaded forms (regularsubmitlisteners won't work for content added after page load). - Added
e.preventDefault()to block the default form submission behavior (which causes a page refresh). - Sent form data via Ajax, then updated the
output_string_lengthdiv with the returned length value. - Added logic to hide the output when switching forms for a cleaner user experience.
Step 3: Verify CSRF Token Handling
Your forms already include {% csrf_token %}, and jQuery automatically includes this token when using serialize() (since it's part of the form data), so no extra code is needed here. Just confirm your base.html includes the jQuery script (which it does).
Optional: Simplify controllers.py
Since we're now passing the actual string instead of a model instance, you can clean up your get_length function:
def get_length(name): return len(name)
That's it! Now when you select an option from either form and click "Process", the length will appear below the form without any page refresh.
内容的提问来源于stack exchange,提问作者Kiran Racherla

