Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 2453

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T05:33:07+00:00 2024-11-26T05:33:07+00:00

How To Upload Image and Text from React to Django with JSON and Proper Encoding.

  • 61k

Uploading only text as JSON from React to Django is quite straightforward. Django serializers easily convert JSON to python native data types. JSON is just like python dictionary in strings(quotes).

But then, how can we send images along with text?. Well, sending image files fixed in the react component state by e.target.files[0] did not work.

A little research brought up the idea of encoding the images as base64!!😈

Okay..okay, Don't let that scare you.

Two or three lines on the frontend, we are done. We don't even need to install anything. Same thing on the backend, 2 lines and we just need to pip install a little package.

We don't even need any header on the frontend, except you are sending an authorization token. We don't even need parsers in the API.

Highlights.

NB: This is not a tutorial on setting up Django with React. A good tutorial on that would be a YouTube series by Brad Traversy (Traversy Media), Full stack React and Django.
For pure Django, then Django Tutorials by Corey Schafer.

We are gonna be using a Post model as an example (Like a Blog Post).

THE BACKEND (DJANGO REST)

  • Create the Post Model
  • Adding MEDIA_URL and MEDIA_ROOT to settings.
  • Pip installing drf_extra_fields (the only installation)
  • Create the serializers
  • Create the API
  • Set up the url.

THE FRONTEND ( REACT )

  • Set up the PostCreate component with state and onChange attribute.

  • Adding the Image change handler, conversion of the image to base64 with FileReader.

  • Setting up axios and sending the JSON data with the base64 representation.

NOW LET'S GO INTO DETAILS

THE BACKEND

1. Create the Post model

We will start by creating the Post model

from django.db import models from django_resized import ResizedImageField from django.utils.text import slugify from django.utils import timezone from django.urls import reverse from django.contrib.auth.models import User   class Post(models.Model):     title = models.CharField(max_length=150)     slug = models.SlugField(blank=True)     file = models.ImageField(null=True,upload_to = 'post_pics',blank=True)     date_posted = models.DateTimeField(default = timezone.now)     content = models.TextField()      def __str__(self):         return f'Post : {self.title}'      def save(self, force_insert=True ,*args , **kwargs):          if not self.slug:             super().save(*args,**kwargs)             pk=str(self.pk)             slug_field = slugify(self.title) + pk             self.slug = slug_field             return super().save(*args,**kwargs)          return super().save(*args,**kwargs)      def get_absolute_url(self):         return reverse('post-detail',kwargs ={"slug":self.slug})  
Enter fullscreen mode Exit fullscreen mode

The image field takes null=True to allow image upload to be optional.

2.) Adding MEDIA_URL and MEDIA_ROOT to settings.

Next, we'll add MEDIA_ROOT AND MEDIA_URL to Django settings.py to enable us to create a local storage location for the uploaded images.

MEDIA_ROOT = os.path.join(BASE_DIR,'media') MEDIA_URL = '/media/' 
Enter fullscreen mode Exit fullscreen mode

3.) Pip installing drf_extra_fields (the only installation)

This is the only installation we will be doing in this tutorial. We need to use the Base64ImageFieldin the package to accept the base64 data.

pip install drf_extra_fields 
Enter fullscreen mode Exit fullscreen mode

4.) Create the Serializer class

from rest_framework import serializers from .models import Post, Review  from drf_extra_fields.fields import Base64ImageField  class PostSerializer(serializers.ModelSerializer):     file = Base64ImageField()      class Meta:         model=Post         fields= ('title','file','content') 
Enter fullscreen mode Exit fullscreen mode

Notice how the file field was set to be the Base64ImageField. The field will receive the base64 data and will allow for conversion back to an image.

5.) Create the API

from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated from .models import Post from .serializers import PostSerializer,    class PostAPI(APIView):     permission_classes = [IsAuthenticated]     def post(self,request,*args,**kwargs):         serializer = PostSerializer(data=request.data)         serializer.is_valid(raise_exception=True)         instance = serializer.save()         response = {        "title":instance.title,"content":instance.content,"date":instance.date_posted.strftime("%a %H:%M %d/%m/%y"),"file":instance.file.url,             "url":instance.get_absolute_url()         }         return Response(response) 
Enter fullscreen mode Exit fullscreen mode

The api gets the JSON data from the frontend, passes into the serializer, which validates and saves the data with the base64 being converted back to an image. Finally it accesses the properties of the saved instance including the url of the saved image and sends it back. I am not sending back the image to the frontend, but rather, a link to the saved image on my local drive.

You might be thinking why not send back as base 64.. Well, that would mean I can't open up the storage location and view. Also, in the frontend, I'll have to convert again from base64. So I didn't bother. So I think it is better this way.

6.) Set up the url.

from django.urls import path from .api import PostAPI   urlpatterns=[     path('api/create',PostAPI.as_view()),]  
Enter fullscreen mode Exit fullscreen mode

Here, we set up the URL necessary to link the react request to the api.

That's it for the Backend..

THE FRONTEND (REACT)

1. Setting up the PostCreate component with state and onChange attribute.

import React, {Component} from "react" import axios from "axios"  class PostCreate extends Component{      state = {         title: "",         content: "",         file: ""     }       onchange=(e) =>{         this.setState({[e.target.name] : e.target.value})     }      render(){          const { title, content, file} = this.state          return(             <div className = 'create-form'>                 <h4 align="center" className = 'createpost-heading'>Start A New Topic</h4>                 <span className ="create-post-requirement">A Title is Enough To Start.. </span>                 <form onSubmit={this.onsubmit}>                     <div className = 'form-field'>                         <span className= "asterik-field">*</span>                         <label className= "post-create-label-first" htmlFor = "id_title">Title</label><br/>                         <input id = "id_title"                         className = 'user-field'                         type ='text'                         name ='title'                         placeholder=' Title of Post'                         size = '110'                         maxLength = '100'                         value = {title}                          onChange={this.onchange}                         />                      </div><br/>                       <div id="post-create-text" className = 'form-field'>                         <label className= "post-create-label" htmlFor = "id_content">Write Something</label>                         <textarea id = 'id_content'                         className = 'content-write'                         type ='text'                         name ='content'                         placeholder=' Write post content'                         rows = '7'                         cols = '25'                         value = {content}                         onChange={this.onchange}>                         </textarea>                     </div> <br/>                      <div id="post-create-image" className = 'form-field'>                         <label className= "post-create-label" htmlFor = "id_postimage">Upload A Game Pic</label>                         <input id = "id_postimage"                          className = 'post-image-field'                          type ='file'                          accept = 'image/*'                         name = 'file'                          />                     </div><br/>                      <button type = "submit" className = 'form-button'>Submit</button><br/>                  </form>         </div>          )     } }   export default PostCreate 
Enter fullscreen mode Exit fullscreen mode

Here, we have created the component for post creation and put in the fields. We have also set the onChange handler for the title and content fields.

2.) Adding the Image change handler and conversion of the image to base64 with FileReader.

Now let's set up the handler for the image field. You'll see the base64 encoding by FileReader in action here.😈

imageChange = (e) =>{         const file = e.target.files[0]         const reader = new FileReader()         reader.onload = () => {             this.setState({file : reader.result})         }          if(file){             reader.readAsDataURL(file)         }      } 
Enter fullscreen mode Exit fullscreen mode

Now, what happens here is very simple. The first line gets the uploaded file under the file variable. The next line creates a FileReader object. Let's visit the last block before the reader.onload. The last block calls reader.readAsDataURL on the file and converts it to base64 format. The reader.onload runs an arrow function when reader.readAsDataURL is triggered to handle a file i.e just like an event Listener. The arrow function simply sets the state with the base64 file.

3.)Setting up axios and sending the JSON data with the base64 representation.

We are gonna be setting up the axios in the onSubmithandler function, so that the axios request is triggered on submission.

onsubmit = (e) =>{         e.preventDefault();         const {title,content,file} = this.state         const token = localStorage.token         let config={}          if(token){              config = {                 "headers": {"Authorization":`Token ${token}`                   }              }         }          const body = {title,content,file}         console.log(body)         axios         .post("api/create",body,config)          .then(             (res) => {                 console.log(res)             }         )        .catch(             (err)=>{                 console.log(err.response)            }        )     } 
Enter fullscreen mode Exit fullscreen mode

Token was used for authentication explaining the token setting in the header. Using JSON.stringify wasn't necessary on the body before sending. The operation is quite simple. After preventing default submission with e.preventDefault , the fields were extracted from the state, and token, from localStorage. The axios request comes in to finish the job by sending the data and handling success with .then, and failure with .catch

VERSIONS OF TOOLS

 Python == 3.7.2,  Django == 3.2.13,  drf-extra-fields == 3.4.0, "react": "^18.0.0", "react-dom": "^18.0.0", "webpack": "^5.70.0", "webpack-cli": "^4.9.2", "axios": "^0.27.1", "react-router-dom": "^6.3.0", "@babel/core": "^7.17.9", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", "babel-loader": "^8.2.4", "babel-plugin-transform-class-properties": "^6.24.1" 
Enter fullscreen mode Exit fullscreen mode

And that's a wrap! I hope you enjoyed the article. I'd love to read/hear your comments. 😊

djangojsonreactwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers
  • Author

    Refactoring for Efficiency: Tackling Performance Issues in Data-Heavy Pages

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.