NextJS and Django Rest Framework Pagination
Updated at: 03 Feb 2025Deepak PainkraIn 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,
For app
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
and
Frontend Part
First, create an app while issuing this command,
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.