Django中Follow按钮无响应问题排查:是否源于JavaScript代码故障?
Hey there! Let's dig into why your follow/unfollow button isn't working. While JavaScript is a likely culprit, we'll also check related parts of your Django code since issues can creep up anywhere in the stack. Here are the most probable fixes:
1. Missing CSRF Token in AJAX Request
Django requires a CSRF token for all POST requests to prevent cross-site request forgery, and your current AJAX call doesn't include it. This will silently fail with a 403 Forbidden error, which explains why nothing happens when you click the button.
Fix: Add the CSRF token to your AJAX request. First, add a helper function to retrieve the token from cookies, then include it in the request headers:
{% block domready %} // Helper to get CSRF token from cookies function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken'); $('a.follow').click(function(e){ e.preventDefault(); const $button = $(this); // Reference the clicked button specifically $.post('{% url "user_follow" %}', { id: $button.data('id'), action: $button.data('action') }, { headers: { 'X-CSRFToken': csrftoken, 'X-Requested-With': 'XMLHttpRequest' // Needed for your ajax_required decorator } }, function(data){ if (data['status'] == 'ok') { const previousAction = $button.data('action'); // Toggle button state $button.data('action', previousAction === 'follow' ? 'unfollow' : 'follow'); $button.text(previousAction === 'follow' ? 'Unfollow' : 'Follow'); // Update follower count const currentCount = parseInt($('span.count .total').text()); $('span.count .total').text(previousAction === 'follow' ? currentCount + 1 : currentCount - 1); } } ); }); {% endblock %}
2. jQuery Not Loaded or domready Block Missing
Your JavaScript uses $ (jQuery syntax), but if jQuery isn't loaded in your base.html, the click event won't bind at all. Also, ensure your base.html includes the {% block domready %}{% endblock %} placeholder—without it, the JS in your user_detail.html won't be rendered.
Check:
- Add jQuery to your base template (before the closing
</body>tag):<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> {% block domready %}{% endblock %}
3. Deprecated request.is_ajax() in Decorator
Django 3.1+ deprecated request.is_ajax() because it relies on the X-Requested-With header, which isn't sent by default in some AJAX setups. Your ajax_required decorator uses this method, so it might be rejecting valid requests.
Fix: Update the decorator to check for the X-Requested-With header explicitly:
from django.http import HttpResponseBadRequest def ajax_required(f): def wrap(request, *args, **kwargs): if request.headers.get('X-Requested-With') != 'XMLHttpRequest': return HttpResponseBadRequest() return f(request, *args, **kwargs) wrap.__doc__ = f.__doc__ wrap.__name__ = f.__name__ return wrap
(Note: We added X-Requested-With: XMLHttpRequest to the AJAX headers in step 1 to make this work.)
4. Global Selector Issues in JavaScript
Your original JS uses $('a.follow') to update the button state, which will target all follow buttons on the page. If you ever have multiple buttons (e.g., on a user list), this will cause bugs. Using $(this) (stored as $button in our fix) ensures only the clicked button is updated.
5. Verify Route Order and URL Generation
Double-check that your user_follow route is defined before any catch-all routes that might match it. In your current urls.py, path('users/follow/',...) comes before path('users/<str:username>/',...), which is correct—so /users/follow/ won't be mistaken for a user profile page.
You can also verify the URL generated by {% url "user_follow" %} by inspecting the page source in your browser. It should render to /users/follow/ (or your app's base path plus that).
6. Check Browser Console for Errors
Open your browser's developer tools (F12) and go to the Console tab. Look for errors like:
$ is not defined: jQuery isn't loaded.403 Forbidden: CSRF token missing.404 Not Found: Incorrect URL foruser_follow.500 Internal Server Error: Bug in youruser_followview.
These errors will point you directly to the root cause.
7. Validate the Followers Relation
Ensure your User.followers relation is working correctly. In your models.py, you added a many-to-many field with related_name='followers', so user.followers.count() should return the correct number of followers. Test this in the Django shell to confirm:
from django.contrib.auth.models import User user = User.objects.get(username='testuser') print(user.followers.count()) # Should show the right count
内容的提问来源于stack exchange,提问作者zeratul314

