How can I upload an image file using VueJS and Django Rest Framework?

Hello, I am currently in the process of editing a blog page using VueJS and Django Rest Framework. However, I am facing an issue when trying to upload a photo - I keep receiving an error message stating that "the sent data is not a file." Additionally, I am unable to select the current image as the default image is Null. My queries are how to create a functional photo change form and how to begin with the image already loaded in the JSON file. Thank you for any assistance provided. Please note that I have not yet set up the admin system.

VueJS

<template>
    <h1>ARTICLE</h1>
    <form @submit="onSubmit">
        <input type="text" name="title" placeholder="Title" v-model="form.title">
        <input type="text" name="desc" placeholder="Description" v-model="form.desc">
        <input type="text" name="category" v-model="form.category">
        <input type="file" name="image" @change="EditImage" >
        <input type="text" name="author" v-model="form.author">
        <input type="text" name="slug" v-model="form.slug">
        <textarea name="text" v-model="form.text"></textarea>

        <button type="submit" @click= "editPost">Edit</button>
    </form>
</template>
<script>
import axios from 'axios';
import { getAPI } from '../api'
export default {
    data () {
        return{
            Postslug: this.$route.params.Postslug,
            form: {
                title:"",
                desc:"",
                text:"",
                category:"",
                date:"",
                author:"",
                image:"",
                slug:"",
            },
            selectedFile: null
        }
    },
    methods: {
        // Form method
        onSubmit(event){
            event.preventDefault();     
            axios.put(`http://127.0.0.1:8000/blog/api/edit/${this.Postslug}`, this.form).then(response => {
              this.form.title = response.data.title
              this.form.desc = response.data.desc
              this.form.text = response.data.text
              this.form.image = response.data.image
              this.form.category = response.data.category
              this.form.author = response.data.author
              this.form.slug = response.data.slug
              alert('Ok')
            })
            .catch(err => {
              console.log(err)
            })
        },
        EditImage(event){
            this.selectedFile = event.target.files[0]
            console.log(event);
        },
        editPost(){
            const fd = FormData();
            fd.append('image', this.selectedFile, this.selectedFile.name)
            axios.put(`http://127.0.0.1:8000/blog/api/edit/${this.Postslug}`, fd)
            .then(response =>{
                console.log(response);
            })
        }
        
    },
    created() {
        getAPI.get(`blog/api/edit/${this.Postslug}`)
            .then(response => {
              this.form.title = response.data.title
              this.form.desc = response.data.desc
              this.form.text = response.data.text
              this.form.date = response.data.date
              this.form.image = response.data.image
              this.form.category = response.data.category
              this.form.author = response.data.author
              this.form.slug = response.data.slug
            })
            .catch(err => {
              console.log(err)
            })
        },
    name: 'AdminEditArticle',
}
</script>
<style lang="sass" scoped>
</style>  

Axios get

import axios from 'axios'
const getAPI = axios.create({
    baseURL: 'http://127.0.0.1:8000',
    timeout: 1000,
})
export { getAPI }

Serializers.py

from rest_framework.fields import ReadOnlyField
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from Blog.models import *

class PostListSerializer(ModelSerializer):
    author = SerializerMethodField()
    category = SerializerMethodField()
    class Meta:
        model = Post
        fields = ('id', 'title', 'author', 'category', 'image', 'desc', 'text', 'slug', 'date')

    def get_author(self, obj):
        return str(obj.author.username)
    
    def get_category(self, obj):
        return str(obj.category.name)


class PostDetailSerializer(ModelSerializer):
    class Meta:
        model = Post
        fields = ('id', 'title', 'author', 'category', 'image', 'desc', 'text', 'slug', 'date')
        def save(self, *args, **kwargs):
            if self.instance.image:
                self.instance.image.delete()
            return super().save(*args, **kwargs)

Models.py

class Post(models.Model): 
    title = models.CharField(max_length=299)
    author = models.ForeignKey(User,default=ANONYMOUS_USER_ID, on_delete=models.CASCADE)
    category = models.ForeignKey(Category,default=ANONYMOUS_USER_ID, on_delete=models.CASCADE)
    image = models.ImageField(blank=True)
    desc = models.TextField()
    text = RichTextField(blank = True, null = True )
    date = models.DateTimeField(auto_now=False, auto_now_add=True)
    slug = models.SlugField(null = True, blank = True, unique=True)

    class Meta: # Order post by date
        ordering = ['-date',]

    def __str__(self): # Display title 
        return self.title

    def get_absolute_url(self): # #TODO da cambiare
        return reverse("listpost")

    def save(self, *args, **kwargs): # Auto Slug Field
        self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

Answer №1

Take a look at the DRF settings for instructions on adding

rest_framework.parsers.FileUploadParser
. This parser is used to parse raw file upload content, where the request.data property will have a dictionary with a key 'file' that contains the uploaded file.

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.BasicAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_FILTER_BACKENDS": [
        "django_filters.rest_framework.DjangoFilterBackend",
        "rest_framework.filters.OrderingFilter",
    ],
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
    "DEFAULT_METADATA_CLASS": "rest_framework.metadata.SimpleMetadata",
    "DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.openapi.AutoSchema",
    "PAGE_SIZE": 50,
    "MAX_LIMIT": 50,
    "TEST_REQUEST_DEFAULT_FORMAT": "json",
    "DEFAULT_RENDERER_CLASSES": (
        "rest_framework.renderers.JSONRenderer",
        "rest_framework.renderers.BrowsableAPIRenderer",
    ),
    "DEFAULT_PARSER_CLASSES": (
        "rest_framework.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        "rest_framework.parsers.MultiPartParser",
        "rest_framework.parsers.FileUploadParser",
    ),
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you explain the significance of the symbol '#' in a Vue Router URL?

I am wondering about the significance of the hash in Vue Router URL. I have noticed that by using mode: 'history', I can eliminate it from the URL. What are the practical differences between having the hash and not having it? ...

Tips for disabling scrolling on touch screens for input elements

I am facing an issue with a modal that is positioned on top of a scrollable document body. I am trying to prevent the scrolling of the document when I swipe my finger on the modal. $(document).on('touchstart touchmove', function(e){ e.preventDef ...

The import 'react-router' does not include an export called 'browserHistory'. This issue is coming from the /src/App.js file

I've recently started diving into the routing section of learning react, but I'm a bit puzzled by the error message I encountered. Error: Failed to compile ./src/App.js 31:19-33 'react-router' does not contain an export named 'bro ...

Hold off on submitting the form until the location has been obtained

I am facing an issue with my application where it tries to retrieve location settings from the browser, which takes some time. I would like this process to run when the page loads so that the data is available when needed. However, if a user clicks the s ...

Activate the button solely when the text field has been populated without any spaces

Searching for a solution to my query, but all the suggestions I've encountered don't consider spaces as valid input. In the join function I have, the button should be disabled if the user enters only spaces. A requirement is for actual text inpu ...

Assign increasing values within an array

Is there a way to efficiently update multiple values in an array by mapping through them? I want to select and change all of them simultaneously. state.formData.forEach(item => { item.EndDate = nextDayIfSelected; }); ...

What is the best way to send a form using ajax?

I am having trouble submitting forms without a post back using AJAX. My code is not working as expected. What could be the issue in my script? I am new to AJAX and would appreciate some help with AJAX scripts. Below you can find my code: Please note: I ...

I am running a Vue.js + Laravel application on a GoDaddy VPS using Putty for compiling, but unfortunately, the changes I make are not reflecting in

Currently, I am working on a Laravel and Vue.js application hosted on a Godaddy VPS. However, I am facing an issue where changes made to the code are not taking effect. Whenever I update the code, I run the following commands in Putty: npm run dev npm ru ...

The issue of time inconsistency in model object save when using datetime.now() in Django

This table shows my admin interface with records ordered by their id in descending order (latest record at top). Below is the code snippet used for creating model objects and saving them: notification = Notification(from_user=from_user, to_user=to_user, ...

Obtain the in-flow position of a DOM element

alert("Incorrect (red): " + document.getElementById("target").getBoundingClientRect().top); alert("Proper (blue): " + document.getElementById("wrapper").getBoundingClientRect().top); #target { transform: translate(20px, -20px) rotateZ(20deg); backgroun ...

Building hierarchical comments in React Native

I'm currently involved in a React Native project that includes a Nested comment section. These comments are retrieved as JSON data and displayed using a FlatList. const App = () => { const [isLoading, setLoading] = useState(true); const [data, ...

Is there a way to maintain the second form's state when the page is refreshed using Vue.js?

I have a challenge in creating a web-app with only 2 pages. The first page requires filling out forms across two stages, but I am unable to create separate pages for this purpose. Is there a way to display two forms on one page and remain on the second for ...

Exploring the globe with 3D raycasting, orbit controls, and dynamic camera rotation

It would be great if users could hover over the small spheres in different countries to get more information. Initially, I thought using a raycaster would help achieve this, but it's not responding to mouse movements as expected. It seems like the is ...

Issue with dynamically added inputs rendering Jquery Masked Input ineffective

Currently facing a challenge while creating a signup form for a project. The issue lies in the functionality of my form which allows users to click an "add contact" button to dynamically generate more input boxes on the page for entering additional user in ...

Navigation from Next.js to a Django page results in the user being logged out of

I'm currently developing a project that involves combining Next.js with Django (using the django-nextjs package) for managing authentication through session-based authentication. Here's how the issue unfolds: Starting from the homepage (a Next.j ...

Ensure to verify localStorage prior to loading the initial route in Vue to check for the presence of

I am currently working on a Vue app that involves some localStorage and server checks upon loading to determine the initial user route. This process takes place in the main entry component of the app, specifically within the created() hook. One issue I&ap ...

Having trouble getting the jquery tabify plugin to work properly

I've put in a lot of effort and double-checked everything, but for some reason this tabify function just won't work. I have gone through my code 100 times but still can't seem to pinpoint the error. Here is the code I am working with: <! ...

Strategies for capturing a 404 error in an Express router

Trying to capture the 404 page not found error in an express router. Using a simple example : const express = require('express'); const app = express(); const router = express.Router(); // ROUTER MID BEFORE router.use((req, res, next) => { ...

The display function in Javascript has a tendency to work sporadically

I’ve been tasked with creating my own tic tac toe game through coding. While I am relatively new to programming, I have a strong passion for it. At the moment, I've set up a basic function to hide only the "O", leaving only the "X" visible on the gr ...

Sending a string parameter from an AJAX function to a Spring controller

I'm currently developing a standalone application and facing an issue with passing a string, which is generated from the change event, to the spring controller using the provided code snippet. Here is the HTML CODE snippet: <!DOCTYPE HTML> < ...