NextJS and Django Rest Framework Pagination

Updated at: 03 Feb 2025Deepak Painkra
 

In this article, we will learn how to create server-components pagination while using the nextjs15 and DRF, so let’s get into the tutorial and let me walk you through the tutorial.

 

So first, let me set up the backend while creating a project and app project,

djano-admin startproject auth
 

For app

python manage.py startapp project
 

Creating a models

After creating the app, create a model ProductType and Product, and this is how you can write the code,

from django.db import models
from django.contrib.auth import User


class ProductType(models.Model):
    title=models.CharField(max_length=200)
    detail=models.JSONField(null=True)
    
    def __str__(self):
      return self.title

class Product(models.Model):
    title = models.CharField(max_length=250, null=True)
    product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    product_no = models.CharField(max_length=100,null=True)
    product_desc = models.TextField(null=True)

    def __str__(self):
      return f' {self.product_no}-{self.product_type}'
    

In this code, we are inheriting ProductType with Product because ProductType is a parent component, which means if you delete the parent components, both parent and child would be.

 

Class based Pagination

For this project, I’m using class-based pagination. Also, this will apply to the particular class only. To create a class-based pagination, create a file name pagination.py inside the project app.

Write this code inside the pagination.py,

from rest_framework.pagination 
import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
 page_size = 2
 

We are importing the PageNumberPagination and creating a pagination class and page size, so now we are ready to export this component to the views.

 

Creating a Serializers

Now, let me create a serialiser for both models. Import your model from the models.py, and write this code Inside the serializers.py.

from rest_framework import serializers
from . import models


class ProductTypeSerializer(serializers.ModelSerializer):
    product_type_imgs = ProductTypeImageSerializer(many=True, read_only=True)
    class Meta:
        model=models.ProductType
        fields=['id', 'title', 'detail']
        
class ProductSerializer(serializers.ModelSerializer):
    variations = VariationSerializer(many=True, read_only= True)
    class Meta:
        model=models.Product
        fields=['id', 'product_no', 'product_desc','title', 'price']

We have imported our models and filled up the fields to show the frontend, and let’s go ahead and create a view for our models and serialisers.

 

Creating a view

Now, let’s import the ListAPIView, CreateAPIView, Serializers, Models and Class-based Pagination to create a view, and we will pass the classes into the views.

from rest_framework.generics import ListAPIView, RetrieveAPIView
from . import serializers
from . import models
from .pagination import MyPageNumberPagination
from rest_framework.pagination import PageNumberPagination

class ProductTypeListView(ListAPIView):
    serializer_class = serializers.ProductTypeSerializer
    queryset=models.ProductType.objects.all()
    pagination_class = MyPageNumberPagination

class ProductTypeDetailView(RetrieveAPIView):
    queryset=models.ProductType.objects.all()
    serializer_class = serializers.ProductTypeSerializer
   
    

We have successfully created the views.

 

Defining a URL

The file location would be auth/urls.py

Now, let’s define a URL for our views, import views and path, and define the URL for both product and detail view.


from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns=[
    path('admin/', admin.site.urls),
    path('api/', include('project.urls')),
,
   
]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

 

Now, let’s also include this url in the project, and the file location would be Project/urs.py  

from django.urls import path
from .import views

urlpatterns =[
    path('product/', views.ProductTypeListView.as_view()),
    path('product/<int:pk>', views.ProductTypeDetailView.as_view()),
]

 

Registering models to an admin panel

Now, let’s register our models to the admin panel,

from django.contrib import admin
from . import models
from django.utils.safestring import mark_safe

admin.site.register(models.Product)
admin.site.register(models.Order)

After registering, you have to run this command

python manage.py makemigrations
 

and

python manage.py migrate
 

Frontend Part

First, create an app while issuing this command,

npx create-next-app@latest
 

After creating, create a component folder outside of the app directory, then create ProductType.js inside the component folder, and write this code,

import React from 'react'
import Link from 'next/link';
import ProductType from '@/components/ProductType';


async function getData(page_no) {
  if (!page_no) {
    page_no = 1
  }
  const res = await fetch('http://127.0.0.1:8000/api/product/?page=' + page_no, { cache: 'no-store' });
  const data = await res.json();
  return data;
}

export default async function Page({ searchParams }) {
  const page = searchParams.page;
  const producttypes = await getData(page)
  const nextPage = parseInt(page) + parseInt(1);
  const links = []
  if (producttypes.previous) {

    links.push(<Link href={`/product/?page=${page - 1}`}>Previous</Link>);

  }
  for (let i = 1; i < producttypes.count; i++) {

    if (page == i) {

      links.push(<Link href={`/product/?page=${i}`}>{i}</Link>);

    } else {

      links.push(<Link href={`/product/?page=${i}`}>{i}</Link>);

    }
  }
  if (producttypes.next) {
    links.push(<Link href={`/product/?page=${nextPage}`}>Next</Link>);
  }

  return (

    <section>

      <h3>Total Results {producttypes.count}</h3>
      <div>
        {
          producttypes.results.map((item, index) =>
            <ProductType item={item} key={index} />


          )}

        <nav>
          <ul>
            {
              links.map((item, index) => <li>{item}</li>)
            }
          </ul>

        </nav>

      </div>


    </section>

  );
} 

After creating a component, create a folder named product inside the app folder, and create page.js inside the product folder, then write this code inside the page file.

'use client'
import Link from "next/link";
import {useEffect, useState} from "react";


export default function ProductType({item}){
    
   
    
    return(
       
        <div>
           <Link href={`product/${item.title}`}>
           {item.title}
           </Link>
           <button>Add to Cart</button>
        </div>
    )
}
 

Creating a slug

Now, create a [slug] folder inside the product folder, then create page.js inside the [slug] folder.

import React from 'react'

const page = () => {
  return (
    <div>page</div>
  )
}

export default page

There we go, and we have created NextJS and DRF server component pagination.

Support Us

Your support helps us continue our work. Please consider making a donation.

Donate with PayPal