Добавление 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>
Вернуться на верх