Python Web Project Examples

This page provides examples of using Mill as a build tool for Python web applications. It includes setting up a basic "Hello, World!" application and developing a fully functional TodoMVC app with Flask and Django, showcasing best practices for project organization, scalability, and maintainability.

Flask Hello World App

This example uses Mill to manage a Flask app that serves "Hello, Mill!" at the root URL (/), with Flask installed as a dependency and tests enabled using unittest.

build.mill (download, browse)
package build
import mill._, pythonlib._

object foo extends PythonModule {

  def mainScript = Task.Source { millSourcePath / "src/foo.py" }

  def pythonDeps = Seq("flask==3.1.0")

  object test extends PythonTests with TestModule.Unittest

}

Running these commands will test and run the Flask server with desired outputs.

The app is ready to serve at http://localhost:5000.

> ./mill foo.test
...
test_hello_flask (test.TestScript...)
Test the '/' endpoint. ... ok
...
Ran 1 test...
OK
...

> ./mill foo.runBackground

> curl http://localhost:5000
...<h1>Hello, Mill!</h1>...

> ./mill clean foo.runBackground

Flask TodoMVC App

This is a Flask-based TodoMVC application managed and built using Mill. It allows users to add, edit, delete, and view tasks stored in a Python Data Structure. Tasks can be filtered as all, active, or completed based on their state. The application demonstrates dynamic rendering using Flask’s routing and templating features.

build.mill (download, browse)
package build
import mill._, pythonlib._

object todo extends PythonModule {

  def mainScript = Task.Source { millSourcePath / "src/app.py" }

  def pythonDeps = Seq("flask==3.1.0", "Flask-SQLAlchemy==3.1.1", "Flask-WTF==1.2.2")

  object test extends PythonTests with TestModule.Unittest
  object itest extends PythonTests with TestModule.Unittest

}

Apart from running a web server, this example demonstrates:

  • Serving HTML templates using Jinja2 (Flask’s default templating engine).

  • Managing static files such as JavaScript, CSS, and images.

  • Filtering and managing tasks in-memory using Python data structures.

  • Unit testing using unittest for testing task operations.

  • Integration testing using unittest for end-to-end application behavior.

This example also utilizes Mill for managing dependencies, builds, and tests, offering an efficient development workflow.

The app is ready to serve at http://localhost:5001.

> ./mill todo.test
...
test_add_todo (test.TestTodoApp...) ... ok
test_delete_todo (test.TestTodoApp...) ... ok
test_edit_todo (test.TestTodoApp...) ... ok
test_filter_todos (test.TestTodoApp...) ... ok
test_toggle_all (test.TestTodoApp...) ... ok
test_toggle_todo (test.TestTodoApp...) ... ok
...Ran 6 tests...
OK
...

> ./mill todo.itest
...
test_add_and_list_todos (test.TestTodoAppIntegration...) ... ok
test_delete_todo (test.TestTodoAppIntegration...) ... ok
test_edit_and_list_todos (test.TestTodoAppIntegration...) ... ok
test_toggle_all_todos (test.TestTodoAppIntegration...) ... ok
test_toggle_and_list_todos (test.TestTodoAppIntegration...) ... ok
...Ran 5 tests...
OK
...

> ./mill todo.runBackground

> curl http://localhost:5001
...What needs to be done...

> ./mill clean todo.runBackground

Django Hello World App

This example demonstrates a minimal Django application managed with Mill. It features a simple view that returns <h1>Hello, Mill!</h1> and includes Django’s core functionality for testing and running a development server.

build.mill (download, browse)
package build
import mill._, pythonlib._

object foo extends PythonModule {

  def mainScript = Task.Source { millSourcePath / "src/manage.py" }

  def pythonDeps = Seq("django==5.1.4")

}

Using Mill, we can easily manage dependencies, run Django tests, and launch the server. With just a few commands, the app is ready to serve at http://localhost:5002.

> ./mill foo.run test main -v 2 # using inbuilt `django test`, `main` is the app name, `-v 2` is verbosity level 2
...
System check identified no issues (0 silenced).
test_index_view (main.tests.TestScript...)
Test that the index view returns a 200 status code ... ok
...
Ran 1 test...
OK
...

> ./mill foo.runBackground runserver 5002

> curl http://localhost:5002
...<h1>Hello, Mill!</h1>...

> ./mill clean foo.runBackground

Django TodoMVC App

This Django TodoMVC example is a task management application built using Mill Build Tool. It features dynamic HTML rendering with Django’s template engine, CRUD operations with Django ORM, and efficient form handling for managing tasks.

build.mill (download, browse)
package build
import mill._, pythonlib._

object todo extends PythonModule {

  def mainScript = Task.Source { millSourcePath / "src/manage.py" }

  def pythonDeps = Seq("django==5.1.4")

}

Apart from running a web server, this example demonstrates:

  • Serving HTML templates using Django’s template engine.

  • Managing static files such as JavaScript, CSS, and images.

  • Querying a SQL database using Django ORM with an SQLite backend.

  • Filtering and managing tasks using SQLite database.

  • Unit + Integration testing using Django’s inbuilt testing framework.

  • URL routing and views for CRUD operations.

This Mill Build File simplifies dependency management, database migrations, and testing workflows.

Running these commands will test and run the Django Todo App. The app is ready to serve at http://localhost:5003.

> ./mill todo.run makemigrations
...Migrations for 'main'...
...+ Create model Todo...

> ./mill todo.run migrate
...Operations to perform...
...Apply all migrations: admin, auth, contenttypes, main, sessions...
...Running migrations...
...OK...

> ./mill todo.run test main -v 2
...Found 8 test(s)...
test_add_todo_view (main.tests.TodoAppTests...) ... ok
test_clear_completed_view (main.tests.TodoAppTests...) ... ok
test_delete_todo_view (main.tests.TodoAppTests...) ... ok
test_edit_todo_view (main.tests.TodoAppTests...) ... ok
test_index_view (main.tests.TodoAppTests...) ... ok
test_list_todos_view (main.tests.TodoAppTests...) ... ok
test_toggle_all_view (main.tests.TodoAppTests...) ... ok
test_toggle_todo_view (main.tests.TodoAppTests...) ... ok
...Ran 8 tests...
...OK...

> ./mill todo.runBackground runserver 5003

> curl http://localhost:5003
...What needs to be done...

> ./mill clean todo.runBackground