← All insights
AI Engineering · May 10, 2024 · 7 min read

Chat With Your Data: Integrating PandasAI in Django Admin

Django admin is where a lot of internal business tooling lives. It's fast to build, it's secure out of the box, and it handles the basics well. But the moment a non-technical stakeholder wants to ask a question like "how many users signed up last week by country, broken down by plan type?" — they're either blocked until an engineer writes a custom view, or they're exporting to CSV and wrestling with spreadsheets.

PandasAI is an open-source library that adds a natural language interface to Pandas DataFrames. Combined with Django admin, it becomes a quick way to give non-technical users self-service access to business data without building a full BI tool.

What PandasAI does

PandasAI wraps a Pandas DataFrame with an LLM-powered interface. You can ask questions in plain English and get back charts, tables, or calculated values:

from pandasai import SmartDataframe
import pandas as pd

df = SmartDataframe(pd.DataFrame(data))
df.chat("What were the top 5 products by revenue last month?")

Under the hood, PandasAI converts the natural language query to Pandas code via an LLM, executes it against the DataFrame, and returns the result. It supports OpenAI, Anthropic, Ollama, and other backends.

Integrating with Django admin

The integration has three parts: a view to load the data and handle the query, a form for user input, and a template to display the result.

First, create a custom admin view:

# admin.py
from django.contrib import admin
from django.shortcuts import render
from django.http import HttpResponse
from pandasai import SmartDataframe
from pandasai.llm import OpenAI
import pandas as pd
from .models import Order

class OrderAdmin(admin.ModelAdmin):
    def get_urls(self):
        from django.urls import path
        urls = super().get_urls()
        custom_urls = [
            path('chat/', self.admin_site.admin_view(self.chat_view), name='order-chat'),
        ]
        return custom_urls + urls

    def chat_view(self, request):
        result = None
        if request.method == 'POST':
            question = request.POST.get('question')
            qs = Order.objects.values('created_at', 'total', 'country', 'plan')
            df = pd.DataFrame(list(qs))
            llm = OpenAI(api_token=settings.OPENAI_API_KEY)
            smart_df = SmartDataframe(df, config={"llm": llm})
            result = smart_df.chat(question)
        return render(request, 'admin/order_chat.html', {'result': result})

admin.site.register(Order, OrderAdmin)

Security considerations

This pattern has a real security surface to manage:

  • Scope the DataFrame — only include the columns users should see. Don't pass the full queryset; select only the fields relevant to the queries you want to enable. Never include PII unless explicitly needed.
  • Restrict to admin users — the admin_view wrapper requires authentication. Add permission checks for sensitive data views.
  • LLM prompt injection — a user could construct a question designed to manipulate the LLM into generating code that accesses more than the DataFrame. PandasAI runs in a sandboxed execution context, but review the library's sandbox configuration before deploying.
  • API cost controls — every query hits the LLM API. Set rate limits per user or add a query approval flow for high-cost queries (e.g., queries that load large DataFrames).

When this is worth doing

This pattern is best suited to internal tools where:

  • The primary users are trusted (internal team, not external customers)
  • The data fits in memory as a DataFrame (up to a few million rows, depending on your server)
  • The alternative is building and maintaining custom admin views for every ad-hoc query request

For larger datasets, consider sampling or aggregating before loading into the DataFrame, or look at tools like Metabase or Redash which are purpose-built for this use case. PandasAI in Django admin is the right tool for teams that already live in Django admin and want to avoid standing up a separate BI stack.

What it replaces

Before this pattern, every stakeholder question that couldn't be answered by the built-in list view became a developer task: write a custom changelist filter, add a calculated field, or export to CSV. This adds up to a non-trivial fraction of engineering time at small companies.

A natural language interface doesn't replace all of that — complex dashboards still need dedicated tooling. But for the long tail of "can you just tell me..." questions, it's a fast way to unblock stakeholders without writing custom code for every question.

Still reading? Good. Book a 30-minute call.

No sales pitch. We'll ask what's on fire and tell you if we can help. If we can't, we'll name three firms who can.

Book a call →