Ollama Django Chat Web App
Video Demo: https://www.youtube.com/watch?v=RlSToUnzF4U
Description:
For my CS50 final project, I built a full-stack web application that provides a browser interface for running local AI models through Ollama. The app supports model selection, conversation management, persistent message history, optional context tracking, automatic summarization, and user account management. The point was to build something real that I’ll actually use after CS50, not just a one-off demo.
I chose Django for this project after using Flask in Week 9. Flask made sense for Finance and it felt simple, but I wanted experience with a more complete framework that includes authentication, database modeling, and a standard project structure. Django is also common in real jobs, so it felt like a good time to force myself to learn it. I did the official Django tutorial first, then used ChatGPT heavily while implementing features and solving problems. I’m not pretending I built this with zero AI help — I used it like a development partner — but I still made the actual design decisions and stitched the system together.
What the project does
The core feature is a chat UI that sends messages to a locally running Ollama server (via HTTP) and displays the model’s response in the browser. Users can:
Create multiple conversations and switch between them
Persist conversations and messages in a database
Select which Ollama model to use (per conversation)
Toggle “use context” on/off per message
Keep recent history for continuity
Summarize older messages into short “factual memory” to avoid sending huge context forever
Delete conversations
Create accounts, log in, change password/email, and delete accounts
File overview (what I wrote and why it exists) chat/models.py
Defines the database schema:
Conversation: belongs to a user, stores title/model, timestamps
Message: belongs to a conversation, stores role (user/assistant), content, timestamp, and a use_context flag
This is what makes conversation history persistent and lets the sidebar exist.
chat/views.py
This is the core backend logic.
chat() (the API endpoint): Receives JSON from the frontend, selects/creates a conversation, optionally loads history from the database, updates session state, and calls Ollama at http://127.0.0.1:11434/api/chat. It saves both user prompts and assistant replies into the database and returns JSON back to the browser.
Summarization logic (summarize_history() + compress_summary()): When history exceeds a threshold, older messages are summarized using the AI model and stored in session as “memory”. If that memory gets too long, it’s compressed again. The goal is to keep context without sending the full chat log forever.
Conversation endpoints:
conversations() returns the conversation list for the sidebar
conversation_detail() returns a conversation + messages so the frontend can reload it
delete_conversation() deletes a conversation and clears session state if it was active
models() calls Ollama’s /api/tags endpoint to load available local models into the dropdown.
account/views.py
Handles authentication/account UI and actions:
login/logout/register
account page for changing password/email (using Django forms)
delete account (password confirmation)
I kept this separate from chat on purpose so the chat app stays focused and account logic isn’t scattered everywhere.
chat_rules.json
Configuration for behavior:
system prompt (including strict math formatting rules)
summarization/compression prompts
how many recent turns to keep
summary size limits
This exists so I can tweak behavior without rewriting code.
static/script.js
This drives most of the interactive behavior:
Sends user messages to /chat/api/ via fetch and renders JSON responses
Loads models from /chat/models/
Loads conversations into a sidebar and supports switching/deleting
Stores selected model in localStorage
Auto-resizing textarea, Enter-to-send behavior
Context toggle support (useContext)
Math rendering and code highlighting
A keyboard listener that focuses the chat box automatically when typing (so it feels like a real chat app)
Design choices (why I did it this way)
Django vs Flask: I wanted something more “real-world” and opinionated, especially for auth and database structure. Django also pushed me to learn how bigger projects are typically organized.
Separate apps (chat + account): It kept the project sane. Chat logic changes constantly; auth logic should be stable and isolated.
Session + database for context: The database stores everything permanently, but I keep “active” context in session so I don’t have to re-query/rebuild state on every request. When switching conversations, the session history is rebuilt from the database.
Summarization approach: Local models slow down when you keep feeding them huge histories. Summarizing older messages into “factual memory” lets the conversation stay consistent without ballooning context size forever.
Frontend in JavaScript instead of full Django forms: Chat UI needs to feel instant and interactive. Fetching JSON and rendering messages dynamically made the app feel like a modern chat interface instead of a page-refresh form.
Running the project
This project requires Ollama to be installed locally and running, with the API available at http://127.0.0.1:11434. At least one model must be installed (for example qwen2.5:7b-instruct). It also requires Python with Django and the project’s dependencies installed (see requirements.txt).