首页 > 解决方案 > 使用 AJAX 更新 Django 模型

问题描述

我试图了解如何使用 AJAX更新Django 模型,而无需加载新页面或明确让用户按下保存按钮。我找到了许多关于使用 AJAX 从 Django 模型中获取结果的教程,但我还没有找到任何关于使用 AJAX 更新模型的教程。

这是我到目前为止所拥有的

我有以下 Django 模型:

#models.py 

class Upload(models.Model):
    email = models.EmailField()
    title = models.CharField(max_length=100)
    language = models.ForeignKey('about.channel', on_delete=models.CASCADE, default='Other')
    date = models.DateField(auto_now_add=True)
    file = models.FileField()
    completed = models.BooleanField(default=False)

我通过表格接受这些上传,一切都很好。然后我通过以下视图在页面上显示它们:

#views.py

def submissions(request):
    context = {
        'uploads': Upload.objects.all().order_by('-completed', '-date')
    }

    return render(request, 'content/submissions.html', context)

此页面的模板:

#submissions.html

            <div class="row row-cols-1 row-cols-md-3">
                {% for upload in uploads %}
                <div class="col mb-4">
                    <div class="card">
                        <div class="card-body">
                            <h5 class="card-title"> {{ upload.title }} </h5>
                            <h6 class="card-subtitle"> {{upload.language}} </h6>
                            <a href="{{ upload.file.url }}" class="channel-link card-link" download> Download </a>
                            {% if upload.completed %}
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" value="" data-id="{{ upload.id }}" checked>
                                    <label class="form-check-label" for="{{ upload.id }}"> Completed </label>
                                </div>
                            {% else %}
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" value="" data-id="{{ upload.id }}">
                                    <label class="form-check-label" for="{{ upload.id }}"> Completed </label>
                                </div>
                            {% endif %}
                        </div>
                    </div>
                </div>
            {% endfor %}
            </div>

这是页面的一部分: 页面说明

completed复选框起作用,并在模型字段上返回适当的选中与未选中。

我正在尝试了解如何将其连接到 AJAX,以便能够通过completed单击页面上每张卡上的复选框来更新模型字段,而无需加载新页面/模型或按下保存按钮。我尝试了以下视图来更新模型,但没有运气:

#views.py

def completed(request, *args, **kwargs):
    upload = Upload.objects.get(id=id)
    upload.completed = not upload.complete
    upload.save()

    return JsonResponse({'status': 200})

和 jQuery/AJAX:

$('.form-check').on('click', '.form-check-input', function() {
    var dataID = $(this).data('id');
    $.ajax({
        type: 'POST',
        url: 'content/completed/',
        data: {
            id: dataID
        },
        success: function () {
            console.log('Success')
        }
    })
});

唉,我什么都得不到。我确定我用来更新的视图和 AJAX 调用都有问题,但我不知道下一步该做什么。

标签: javascriptjquerydjangoajaxdjango-models

解决方案


我假设您的表单使用正确的数据成功触发了您的 AJAX 调用。也许您没有正确访问您的 AJAX post 参数

你的 API:

def completed(request)
    id = request.POST.get('id')   # Add this line

    upload = Upload.objects.get(id=id)
    upload.completed = not upload.complete
    upload.save()
    
    return JsonResponse({'status': 200})

如果这不能解决问题,请告诉我您从后端收到了哪些消息,以及您在 Ajax 调用中发送了哪些类型的数据。如果您使用 FireFox,请按 ctrl+shift+I 并单击 Network 选项卡以查看您从 Ajax 调用发送的数据。

关于您对 CSRF 的评论,请尝试在调用 $.ajax() 之前放置此代码(csrfSafeMethod() 和 $.ajaxSetup())

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};

...

$('.form-check').on('click', '.form-check-input', function() {
    var dataID = $(this).data('id');
    
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                // Only send the token to relative URLs i.e. locally.
                xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
            }
        }
    });

    $.ajax({
        url: "content/completed/",
        type: "POST",
        data: {
            id: dataID
        },
        success: function () {
            console.log('Success')
        }
    })
});

这就是我为我的 API 处理 CSRF 而不将它们放入 @csrf_exempt 的方式,也许它也对你有用


推荐阅读