Добавление POST-запроса через компонент Vue и Fetch API для добавления объекта в бэкенд Django
SPA: VueJS
Backend: Django default
Хотя на данный момент я сосредоточен на POST, вот над чем я работаю:
- просмотр списка всех элементов в модели (мой список извлекается через GET-запрос сразу после загрузки страницы)
- добавление нового элемента в список через Vue (POST)
- обновить детали отдельных элементов (PUT)
- удаление элемента (DELETE)
- запросы от моего клиента к моему серверу выполняются через Ajax запросы с использованием fetch API. Поэтому после загрузки первой страницы я не хочу, чтобы происходило дальнейшее обновление страницы.
Я хочу добавить простую форму, которая при отправке будет делать пост-запрос и добавлять объект или новый рецепт в мою внутреннюю базу данных. В настоящее время у меня есть метод запроса GET, который использует fetch. Я хотел бы узнать, как данные формы могут быть переданы в список данных, но, что более важно, в результате будет создан объект (возможно, с разбором как JSON-файл).
App.vue
<template>
<div>
<button @click="fetchRecipes">Fetch Recipes</button>
<div>
<ul>
<li v-for="recipe in recipes">
{{ recipe.name }}
<span v-if="!recipe.popular">(Not very popular!)</span>
</li>
</ul>
</div>
</div>
<form> where I would like my form </form>
</template>
<script>
export default {
data() {
return {
recipes: [],
}
},
methods: {
async fetchRecipes() {
// Perform an Ajax request to fetch the list of recipes
let response = await fetch("http://localhost:8000/api/recipes/")
let data = await response.json()
this.recipes = data.recipes
}
}
}
</script>
urls.py
from django.contrib import admin
from django.urls import path
from mainapp.views import index, recipes_api
urlpatterns = [
path('', index),
path('api/recipes/', recipes_api),
]
models.py
from django.db import models
class Recipe(models.Model):
name = models.CharField(max_length=350)
popular = models.BooleanField(default=False)
def __str__(self):
return self.name
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'popular': self.popular,
}
views.py
from django.shortcuts import render
from django.http import HttpRequest, HttpResponse, JsonResponse
from mainapp.models import Recipe
def index(request: HttpRequest) -> HttpResponse:
title = "My App"
return render(request, "mainapp/index.html", {
'title': title,
'n': Recipe.objects.all().count()
})
def recipes_api(request):
if request.method == 'GET':
return JsonResponse({
'recipes': [
recipe.to_dict()
for recipe in Recipe.objects.all()
]
})
Вы можете сделать еще один запрос, используя POST, с телом, содержащим поля объекта, который вы хотите создать. Вам также понадобится объект формы в вашем django (с теми же полями).
Затем вы можете использовать request.POST, чтобы получить то, что ваш вызов запроса отправил в ваше представление django, и создать объект соответственно.
Django form :
class MyForm(forms.Form):
name = models.CharField(max_length=255)
def save():
obj = MyObject()
obj.name = self.cleaned_data["name"]
obj.save()
Django view :
def MyFormView(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
obj = form.save()
return HttpResponse(status=201, content=obj.serialize()) # 201 Created
else:
return HttpResponse(status=400) # 400 bad request
else:
return HttpResponse(status=403) # 403 fobidden, post only creation endpoint
Входной файл Vue JS
<template>
<input
:value="name"
@input="$emit('update:name', $event.target.value)"
/>
<button @click="post">Create my recipe !</button>
</template>
<script>
export default {
props: ['name'],
emits: ['update:name']
},
methods: {
async post() {
let response = await fetch("http://localhost:8000/api/recipes/create", {
method: 'POST',
body: {'name': this.name},
headers: {
'X-CSRFToken': this.csrfToken,
'Content-Type': "application/x-www-form-urlencoded" // You need this to get your POSTed data in the django view
}
});
// handle the response...
}
}
</script>