You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 for user_follow.
  • 500 Internal Server Error: Bug in your user_follow view.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:28:10