A Practical Guide to Building Flexible APIs with APIView
- Introduction: There’s surprisingly little information about using pandas in DRF
- Why pandas is a perfect match for REST APIs
- Why APIView works better than ViewSet when using pandas
- How to convert Querysets into pandas DataFrames safely
- Example 1: A simple API that returns raw data
- Example 2: Monthly aggregation API (common analytics use case)
- Example 3: Formatting data for a Recharts PieChart
- Example 4: Returning multiple datasets in a single dashboard API
- Best practices when using pandas in DRF
- When not to use pandas
- Conclusion: pandas + APIView is the perfect stack for analytics APIs
Introduction: There’s surprisingly little information about using pandas in DRF
Most Django REST Framework (DRF) tutorials focus on:
- simple CRUD operations
- returning model data directly
- using ModelSerializer
But in real-world projects, what you need most often are:
- analytics APIs
- data transformation APIs
- visualization-ready APIs
- multi-table aggregation APIs
These rarely return raw database rows.
This is exactly where pandas becomes incredibly useful.
However, there are very few high-quality guides explaining
“How do I properly use pandas inside DRF?”
This article introduces:
- Why pandas works so well with DRF
- Why APIView is the best choice when using pandas
- Safe patterns for converting Querysets into DataFrames
- Practical examples (raw data, monthly aggregation, Recharts formatting, dashboards)
Why pandas is a perfect match for REST APIs
pandas is designed for data analytics, but its strengths map beautifully to REST API use cases.
✔ Strengths of pandas
- Easy aggregation (groupby, pivot_table, resample)
- Clean handling of missing values
- Powerful type conversions (datetime, numeric, category)
- Simple column renaming
- Easy JSON shaping with
to_dict()
✔ Strengths of DRF
- Routing
- Authentication and permissions
- Request/response handling
- API schema support
Combined, they form a powerful workflow:
Queryset → DataFrame → processing → dict → Response
This pattern is ideal for dashboard- and analytics-oriented APIs.
Why APIView works better than ViewSet when using pandas
ViewSet is optimized for:
- CRUD
- ModelSerializer
- returning data in model-like shapes
But analytics APIs need:
- custom aggregations
- multi-table joins
- deeply customized JSON output
- time-series processing
- transformations unrelated to the DB model
In other words, you need freedom.
→ APIView provides exactly that
- You write plain Python logic
- No serializer constraints
- Easy to integrate with pandas
- Clearer control over input and output
For pandas-heavy APIs, APIView is simply the best option.
How to convert Querysets into pandas DataFrames safely
This is the core operation when working with pandas in DRF.
Basic pattern
qs = Model.objects.all().values()
df = pd.DataFrame(qs)
Best practice: select only the columns you need
qs = Sales.objects.all().values("area", "amount", "date")
df = pd.DataFrame(qs)
Benefits:
- Better performance
- No unnecessary data leakage
- Easier debugging
- Cleaner DataFrame structures
Example 1: A simple API that returns raw data
class RawSalesAPIView(APIView):
def get(self, request):
qs = Sales.objects.all().values("area", "amount", "date")
df = pd.DataFrame(qs)
# Convert date to string for frontend compatibility
df["date"] = df["date"].astype(str)
return Response(df.to_dict(orient="records"))
Why this matters
- Avoids datetime serialization issues
- Provides stable, predictable JSON
- Easy to extend with transformations later
Example 2: Monthly aggregation API (common analytics use case)
class MonthlySalesAPIView(APIView):
def get(self, request):
qs = Sales.objects.all().values("date", "amount")
df = pd.DataFrame(qs)
df["date"] = pd.to_datetime(df["date"])
monthly = (
df.groupby(df["date"].dt.to_period("M"))["amount"]
.sum()
.reset_index()
)
monthly["date"] = monthly["date"].astype(str)
return Response(monthly.to_dict(orient="records"))
Example JSON output
[
{"date": "2025-01", "amount": 3200},
{"date": "2025-02", "amount": 4100}
]
Perfect for line charts or bar charts in React/Recharts.
Example 3: Formatting data for a Recharts PieChart
Recharts expects:
[
{"name": "Area A", "value": 30},
{"name": "Area B", "value": 40}
]
Your backend can generate that easily:
class AreaSharePieAPIView(APIView):
def get(self, request):
qs = Sales.objects.all().values("area", "share")
df = pd.DataFrame(qs)
result = (
df.groupby("area")["share"]
.mean()
.reset_index()
.rename(columns={"area": "name", "share": "value"})
)
return Response(result.to_dict(orient="records"))
Why pandas is ideal
- groupby operations are simple
- column renaming is flexible
- JSON output is perfectly shaped
Example 4: Returning multiple datasets in a single dashboard API
This is extremely common in dashboards.
class DashboardAPIView(APIView):
def get(self, request):
qs = Sales.objects.all().values()
df = pd.DataFrame(qs)
total = df["amount"].sum()
by_area = df.groupby("area")["amount"].sum().reset_index()
by_target = df.groupby("target")["amount"].sum().reset_index()
return Response({
"total": int(total),
"by_area": by_area.to_dict(orient="records"),
"by_target": by_target.to_dict(orient="records"),
})
This single endpoint can power multiple charts.
Best practices when using pandas in DRF
✔ Convert datetime to string
React/Recharts often fail with Python datetime objects.
✔ Use fillna(0) to prevent frontend crashes
Missing values are dangerous in JS chart libraries.
✔ Always return orient="records"
The most compatible JSON structure.
✔ Prefer APIView over ViewSet for analytics
Cleaner logic and fewer constraints.
✔ Split complex transformations into helper functions
Improves maintainability and testability.
When not to use pandas
Serializer-based DRF shines when:
- Your API performs CRUD
- You need input validation (POST/PUT/PATCH)
- Output matches your database model
- You rely heavily on auto-generated API schemas
For analytics, pandas is almost always the better tool.
Conclusion: pandas + APIView is the perfect stack for analytics APIs
pandas handles transformation and structure.
DRF handles API mechanics and security.
Together they create an ideal environment for:
- dashboards
- aggregated analytics
- competitor comparisons
- segmentation metrics
- chart-ready datasets
If you’ve ever struggled with Serializers for data-heavy APIs,
try using pandas inside APIView.
You’ll find that your code becomes cleaner, faster, and far easier to maintain.

