Chapter 50: Build a Full-Stack App in Python
Put it all together: a complete project. In this chapter, you will learn build a full-stack app in depth with Python code examples, explanations, and best practices.
Overview
This chapter covers build a full-stack app for Kungfu.js developers using Python. We will start with the basics, move through practical examples, and end with advanced techniques and common pitfalls.
Why This Matters
Understanding build a full-stack app is essential because it is a core part of building web applications. Every real-world app needs to handle put it all together: a complete project. Skipping this chapter would leave a gap in your knowledge that would cause problems later.
Code Example
Building a Complete Application
In this final chapter, we will combine everything you have learned into a complete full-stack application. We will build a todo app with:
- Database (SQLite) with CRUD operations
- JWT authentication
- WebSocket for real-time updates
- CSS engine for styling
- SSR with .kng files
- Auto-generated API docs
- Docker deployment
Project Structure
Here is how the complete todo app is organized. Every file is shown below so you can build it yourself without leaving this tutorial:
# app.py — complete todo app
from kungfu import KungfuApp
import json, sqlite3
db = sqlite3.connect('todos.db', check_same_thread=False)
db.execute('CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY, title TEXT, done INTEGER DEFAULT 0)')
app = KungfuApp()
@app.get('/api/todos')
def list_todos(req):
rows = db.execute('SELECT id, title, done FROM todos ORDER BY id DESC').fetchall()
todos = [{'id': r[0], 'title': r[1], 'done': bool(r[2])} for r in rows]
return app.respond(req['request_id'], 200, json.dumps(todos))
@app.post('/api/todos')
def create_todo(req):
body = json.loads(req['body'])
cur = db.execute('INSERT INTO todos (title) VALUES (?)', (body['title'],))
db.commit()
todo = {'id': cur.lastrowid, 'title': body['title'], 'done': False}
return app.respond(req['request_id'], 201, json.dumps(todo))
@app.put('/api/todos/:id/toggle')
def toggle(req):
db.execute('UPDATE todos SET done = NOT done WHERE id = ?', (req['params']['id'],))
db.commit()
return app.respond(req['request_id'], 200, '{"ok":true}')
@app.delete('/api/todos/:id')
def delete(req):
db.execute('DELETE FROM todos WHERE id = ?', (req['params']['id'],))
db.commit()
return app.respond(req['request_id'], 204, '')
app.listen(3000)
How the Pieces Fit Together
The Rust core handles HTTP parsing, routing, and the WebSocket connection. The Python binding registers route handlers that call into the ORM for database operations. The .kng files handle the frontend — data() fetches todos from the API, template() renders them as HTML, and the hydration script makes the page interactive. When a todo is created, the server broadcasts a WebSocket message to all connected clients, and the UI updates in real time without a page refresh.
Running the App
python app.py
# Then open http://localhost:3000 in your browser
Congratulations!
You have completed all 50 chapters of the Kungfu.js tutorial for Python. You now know how to build, secure, test, and deploy production-grade web applications with Kungfu.js.
What to do next:
- Build your own project using what you learned
- Share what you built with the community
- Write about your experience with Kungfu.js
- Help others learn by answering questions
Common Mistakes
- Not reading the documentation: Always check the API reference when something does not work as expected.
- Skipping security: Never disable the default middleware unless you have a very good reason. Security is not optional.
- Not testing: Write tests for your handlers. Kungfu.js makes this easy with the built-in test utilities.
Summary
In this chapter, you learned about build a full-stack app in Python. You saw code examples, understood how things work under the hood, and learned about common mistakes to avoid.