首页 > 解决方案 > 带有 Axios 的 Django 和 Vue.js:发布请求时出现 500 内部服务器错误

问题描述

我目前正在使用Vue.jsDjango(Vanilla Django 不是 Django REST 框架)制作一个 TODO 应用程序,并且我正在使用AXIOS执行请求发布/获取,获取请求工作得非常好,我能够获取数据,但是当我创建一个新任务并使用发布请求将其提交到 Django 后端时,我收到了这些错误。

客户端错误

我在前端收到此错误:

xhr.js:185 POST http://127.0.0.1:8000/tasks/ 500 (Internal Server Error)

createError.js:17 Uncaught (in promise) Error: Request failed with status code 500
at createError (createError.js:17)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:69)

服务器端错误

我在服务器端遇到的错误是:

Internal Server Error: /tasks/
Traceback (most recent call last):
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/lib/python3.8/site-packages/django/views/generic/base.py", line 73, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/lib/python3.8/site-packages/django/views/generic/base.py", line 101, in dispatch
    return handler(request, *args, **kwargs)
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/todo/task/views.py", line 21, in post
    bound_form = TaskForm(request.POST)
  File "/Users/OpenMindes/Dev/web/django-vue-projects/django-vuejs-todo/lib/python3.8/site-packages/django/forms/models.py", line 287, in __init__
    raise ValueError('ModelForm has no model class specified.')
ValueError: ModelForm has no model class specified.
[25/Aug/2020 00:26:25] "POST /tasks/ HTTP/1.1" 500 78624

这是我在前端 HTML 和 javascript 中的代码:

function sendRequest(url, methode, data) {
    const r = axios({
        url: url,
        method: methode,
        data: data,
        xsrfCookieName: 'csrftoken',
        xsrfHeaderName: 'X-CSRFToken',
        headers: {
            'X-Requested-With': 'XMLHttpRequest'
            //to allow django recognizing this request as ajax request
        }
    });
    return r;
}
const app = new Vue({
    el: '#app',
    data: {
        task: '',
        tasks: [],
    },
    //use hooks to call the function at the event of page loaded
    created() {
        const vue_instance_ref = this;
        const r = sendRequest('', 'get')
            .then(function (response) {
                vue_instance_ref.tasks = response.data.tasks;
            });
    },
    methods: {
        createNewTask() {
            const vue_instance_ref = this;
            const formData = new FormData();
            formData.append('title', this.task);
            sendRequest('', 'post', formData)
                .then(function (response) {
                    vue_instance_ref.tasks.push(response.data.newTask);
                    vue_instance_ref.task = '';

                });
        }
    }
});
{% extends 'base.html' %}
{% block content %}
{% verbatim %}
<div id="app">
    <form @submit.prevent="createNewTask">
 {% endverbatim %}
    {% csrf_token %}
 {% verbatim %}
        <div class="form-group row">
            <div class="col-8">
                <label>Create New Task</label>
                <input type="text" class="form-control" v-model="task">
            </div>
            <div class="d-flex flex-column col-4">
                <button class="btn btn-success mt-auto">
                    Create
                </button>
            </div>
        </div>
    </form>
    <div class="mt-5">
        <div class="card my-1" v-for="task in tasks">
            <div class="card-body">
                {{ task.title }}
                <button type="button" class="close float-right">
                    <span>&times;</span>
                </button>
            </div>
        </div>
    </div>
</div>
{% endverbatim %}
{% endblock content %}

后端代码:

from django.db import models

class Task(models.Model):
    TASK_STATUS = [
        ('done','todo'),('todo','todo'),('deleted','deleted'),
    ]
    title = models.CharField(max_length=120)
    created = models.DateTimeField(auto_now_add=True)
    #status = models.CharField(max_length=50,choices=TASK_STATUS)
    isDone = models.BooleanField(default=False)
    class Meta:
        ordering = ['isDone','created']

Forms.py:

from django.forms import models
from task.models import Task

class TaskForm(models.ModelForm):
    model = Task
    fields = ['title']

以及处理 POST|GET 的视图:

from django.shortcuts import render,redirect
from django.views.generic import ListView, View
from django.http import JsonResponse

# Create your views here.
from .models import  Task
from .forms import TaskForm
from django.forms.models import model_to_dict


class TaskView(View):

def get(self,request):
    _tasks = list(Task.objects.all().values())
    if request.is_ajax():
        return JsonResponse({'tasks':_tasks}, status=200)
    return render(request,'task/tasks.html')

def post(self,request):
    bound_form = TaskForm(request.POST)
    if bound_form.is_valid():
        new_task = bound_form.save()
        return JsonResponse({'newTask':model_to_dit(new_task)}, status=200)
    return redirect('tasks-list')

标签: djangovue.jsdjango-formsdjango-templatesaxios

解决方案


在 forms.py 中,模型和字段必须在Meta类中

from django.forms import models
from task.models import Task
class TaskForm(models.ModelForm):
    class Meta:
        model = Task
        fields = ['title']

推荐阅读