Contact Form Using NextJS App Router and DRF

Updated at: 05 Sep 2024Deepak Painkra
 

In this article, we will be creating a contact form by using the NextJS app router and Django Rest Framework, and we are using server action to sumbit the form,

We must install a few packages, such as coreheaders, in order to connect the backend and the frontend.

 

what is coreheaders?

A Django App that adds Cross-Origin Resource Sharing (CORS) headers to responses. This allows in-browser requests to your Django application from other origins.

About CORS
Adding CORS headers allows your resources to be accessed on other domains. It’s important you understand the implications before adding the headers, since you could be unintentionally opening up your site’s private data to others.

 

Run this command in order to install this package.

pip install django-cors-headers
 

and then add it to your installed apps:

INSTALLED_APPS = ["corsheaders","contact","rest_framework,"]
 

You will also need to add a middleware class to listen in on responses:

MIDDLEWARE = ["corsheaders.middleware.CorsMiddleware",]

 

We also need to add origins so that front-end and backend can communicate with one another.

CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", "http://127.0.0.1:3000",]

 

Let's implement some backend code now that the connection portion is finished. We must enter these commands in order to begin the project.

django-admin startproject backend

When this procedure is finished, you will be able to see python manage.py inside the backend folder. In order to establish a contact form, we must create an app by running these commands.

 
python manage.py startapp contact
 

and after that it will create an application with the name contact. To be able to connect to each other, make sure the folder name is the same as the frontend. Let's develop the contact app's components now.

paste this code inside the backend/urls.py

from django.urls import path
from contact import views

urlpatterns = [
  path('contact/', views.ContactView.as_view(), name='contact')
]
 

Go ahead and add this code. We now need to develop a model to enable us to collect data from users via the contact form, contact/model.py

from django.db import models

class Contact(models.Model):
  name= models.CharField(max_length=100)
  email= models.EmailField()
  desc= models.TextField(max_length=500)
 

create a file name serializer.py inside the contact/serializer.py

from pyexpat import model
from rest_framework import serializers
from contact.models import Contact

class ContactSerializer(serializers.ModelSerializer):
  class Meta:
    model=Contact
    fields = ['name', 'email', 'desc']
 

Then, create the file urls.py in the contact folder, and then paste this code inside the contact/urls.py.

from django.urls import path

from contact import views

urlpatterns = [

path('contact/', views.ContactView.as_view(), name='contact')

]

 

then paste this code inside the contact/view.py file

from rest_framework.response import Response
from contact.models import Contact
from contact.serializers import ContactSerializer
from rest_framework.views import APIView
from rest_framework import status

class ContactView(APIView):
  def post(self, request, format=None):
    serializer = ContactSerializer(data=request.data)
    if serializer.is_valid():
      serializer.save()
      return Response({'msg':'Form Sumbitted Successfully', 'status':'success', 'candidate':serializer.data}, status=status.HTTP_201_CREATED)
    return Response(serializer.errors)
  
  def get(self, request, format=None):
    candidates = Contact.objects.all()
    serializer = ContactSerializer(candidates, many=True)
    return Response({'status':'success', 'candidates':serializer.data}, status=status.HTTP_200_OK)

 

Last stps we need to register this app. To register this we need to write these code inside the contact/admin.py

from django.contrib import admin
from contact.models import Contact

@admin.register(Contact)
class ContactModelAdmin(admin.ModelAdmin):
  list_display = ['name', 'email', 'desc']

 

About finished with the backend, we now need to migrate these modifications. Write this command.

 
python manage.py makemigrations
 

to view your admin panel's model. We must additionally issue this command.

 
python manage.py migrate
 

now run the server

python manage.py runserver

You can now used your contact form to submit the form on the database if you run the fronted server in addition to doing so, since refusing to do so would result in an error.

 

Frontend Part

Now, let's go ahead on the fronted part, create a NextJS app by issuing this command,

 
npx create-next-app@latest
 

We are an app router without typescript. First, create a contact folder inside the app folder and create the file name page.js inside the contact folder.

Now let's write the code,

 

'use client'
import { useState } from "react"
 

We will use useState, so let's write "use client" and import useState from react so that we can show the successful message in the contact form,

 

Now, let's write the code and get the JSON response. We are using server action for this project, and if you want to know more, here is the Official Documentation.

 

export default function Page() {

    const [successMsg, setsuccessMsg] = useState(false);

    async function createContact(formData) {

        const fd = {
            name: formData.get('name'),
            email: formData.get('email'),
            desc: formData.get('desc'),
        }
        const res = await fetch('http://127.0.0.1:8000/api/contact/',
            {
                'method': 'POST',
                'body': JSON.stringify(fd),
                'headers': {
                    'Content-Type': 'application/json'
                }
            }
        );

        const resData = await res.json();

        if (res.ok) {
            setsuccessMsg(true);

            setTimeout(() => {
                setsuccessMsg(false);
              }, 3000);
            seterrorMsg(resData.data);

        } else {

            alert('There was an error sending your message.');
        }

    };

    return (
        <div>
            <form action={createContact}>
                <div>

                    {
                        successMsg && <div>Thanks for Contacting us</div>
                    }
                    <label htmlFor="name">Name</label>
                    <input id="name" name="name" placeholder="Name" />
                </div>
                <div>
                    <label htmlFor="email">Email</label>
                    <input id="email" name="email" type="email" placeholder="Email" />
                </div>
                <div>
                    <label htmlFor="desc">Elaborate Your Concer</label>
                    <input id="desc" name="desc" type="text"/>
                </div>
                <button type="submit">Sumbit</button>
            </form>
        </div>
    )
}

 

Now, if the response is OK, we will show the success message and also implement the setTimout function, and this message will disappear after 3 seconds.