100% found this document useful (11 votes)
73 views85 pages

Instant Download Flask Web Development Developing Web Applications With Python 1st Edition Miguel Grinberg PDF All Chapters

Web

Uploaded by

mahmobnabal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (11 votes)
73 views85 pages

Instant Download Flask Web Development Developing Web Applications With Python 1st Edition Miguel Grinberg PDF All Chapters

Web

Uploaded by

mahmobnabal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

Download the full version of the ebook at ebookfinal.

com

Flask Web Development Developing Web Applications


with Python 1st Edition Miguel Grinberg

https://ebookfinal.com/download/flask-web-development-
developing-web-applications-with-python-1st-edition-miguel-
grinberg/

OR CLICK BUTTON

DOWNLOAD EBOOK

Download more ebook instantly today at https://ebookfinal.com


Instant digital products (PDF, ePub, MOBI) available
Download now and explore formats that suit you...

Flask Web Development 1st Edition Miguel Grinberg

https://ebookfinal.com/download/flask-web-development-1st-edition-
miguel-grinberg/

ebookfinal.com

Developing Responsive Web Applications with AJAX and


jQuery 1st Edition Sandeep Kumar Patel

https://ebookfinal.com/download/developing-responsive-web-
applications-with-ajax-and-jquery-1st-edition-sandeep-kumar-patel/

ebookfinal.com

Web Scraping with Python Collecting Data from the Modern


Web 1st Edition Ryan Mitchell

https://ebookfinal.com/download/web-scraping-with-python-collecting-
data-from-the-modern-web-1st-edition-ryan-mitchell/

ebookfinal.com

Developing Web applications with Visual Basic NET and ASP


NET 1st Edition John Alexander

https://ebookfinal.com/download/developing-web-applications-with-
visual-basic-net-and-asp-net-1st-edition-john-alexander/

ebookfinal.com
Web Engineering The Discipline of Systematic Development
of Web Applications Gerti Kappel

https://ebookfinal.com/download/web-engineering-the-discipline-of-
systematic-development-of-web-applications-gerti-kappel/

ebookfinal.com

Web Development with Jade 1st Edition Sean Lang

https://ebookfinal.com/download/web-development-with-jade-1st-edition-
sean-lang/

ebookfinal.com

Enjoying Web Development with Tapestry 1ST Edition Ka

https://ebookfinal.com/download/enjoying-web-development-with-
tapestry-1st-edition-ka/

ebookfinal.com

Building Web Applications with Erlang Working with REST


and Web Sockets on Yaws 1st Edition Zachary Kessin

https://ebookfinal.com/download/building-web-applications-with-erlang-
working-with-rest-and-web-sockets-on-yaws-1st-edition-zachary-kessin/

ebookfinal.com

Web Development with the Mac 1st Edition Aaron Vegh

https://ebookfinal.com/download/web-development-with-the-mac-1st-
edition-aaron-vegh/

ebookfinal.com
Flask Web Development

Miguel Grinberg
Flask Web Development
by Miguel Grinberg
Copyright © 2014 Miguel Grinberg. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/
institutional sales department: 800-998-9938 or [email protected].
Editors: Meghan Blanchette and Rachel Roumeliotis Cover Designer: Randy Comer
Production Editor: Nicole Shelby Interior Designer: David Futato
Copyeditor: Nancy Kotary Illustrator: Rebecca Demarest
Proofreader: Charles Roumeliotis

May 2014: First Edition

Revision History for the First Edition:


2014-04-25: First release

See http://oreilly.com/catalog/errata.csp?isbn=9781449372620 for release details.

Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly
Media, Inc. Flask Web Development, the picture of a Pyrenean Mastiff, and related trade dress are trademarks
of O’Reilly Media, Inc.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as
trademarks. Where those designations appear in this book, and O’Reilly Media, Inc. was aware of a trademark
claim, the designations have been printed in caps or initial caps.
While every precaution has been taken in the preparation of this book, the publisher and authors assume
no responsibility for errors or omissions, or for damages resulting from the use of the information contained
herein.

ISBN: 978-1-449-37262-0
[LSI]
For Alicia.
Table of Contents

Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi

Part I. Introduction to Flask


1. Installation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Using Virtual Environments 4
Installing Python Packages with pip 6

2. Basic Application Structure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7


Initialization 7
Routes and View Functions 8
Server Startup 9
A Complete Application 9
The Request-Response Cycle 12
Application and Request Contexts 12
Request Dispatching 14
Request Hooks 14
Responses 15
Flask Extensions 16
Command-Line Options with Flask-Script 17

3. Templates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
The Jinja2 Template Engine 22
Rendering Templates 22
Variables 23
Control Structures 24
Twitter Bootstrap Integration with Flask-Bootstrap 26
Custom Error Pages 29
Links 31

v
Static Files 32
Localization of Dates and Times with Flask-Moment 33

4. Web Forms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Cross-Site Request Forgery (CSRF) Protection 37
Form Classes 38
HTML Rendering of Forms 40
Form Handling in View Functions 41
Redirects and User Sessions 44
Message Flashing 46

5. Databases. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
SQL Databases 49
NoSQL Databases 50
SQL or NoSQL? 51
Python Database Frameworks 51
Database Management with Flask-SQLAlchemy 52
Model Definition 54
Relationships 56
Database Operations 57
Creating the Tables 58
Inserting Rows 58
Modifying Rows 60
Deleting Rows 60
Querying Rows 60
Database Use in View Functions 62
Integration with the Python Shell 63
Database Migrations with Flask-Migrate 64
Creating a Migration Repository 64
Creating a Migration Script 65
Upgrading the Database 66

6. Email. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Email Support with Flask-Mail 69
Sending Email from the Python Shell 70
Integrating Emails with the Application 71
Sending Asynchronous Email 72

7. Large Application Structure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75


Project Structure 75
Configuration Options 76
Application Package 78

vi | Table of Contents
Using an Application Factory 78
Implementing Application Functionality in a Blueprint 79
Launch Script 81
Requirements File 82
Unit Tests 83
Database Setup 85

Part II. Example: A Social Blogging Application


8. User Authentication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Authentication Extensions for Flask 89
Password Security 90
Hashing Passwords with Werkzeug 90
Creating an Authentication Blueprint 92
User Authentication with Flask-Login 94
Preparing the User Model for Logins 94
Protecting Routes 95
Adding a Login Form 96
Signing Users In 97
Signing Users Out 99
Testing Logins 99
New User Registration 100
Adding a User Registration Form 100
Registering New Users 102
Account Confirmation 103
Generating Confirmation Tokens with itsdangerous 103
Sending Confirmation Emails 105
Account Management 109

9. User Roles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111


Database Representation of Roles 111
Role Assignment 113
Role Verification 114

10. User Profiles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119


Profile Information 119
User Profile Page 120
Profile Editor 122
User-Level Profile Editor 122
Administrator-Level Profile Editor 124

Table of Contents | vii


User Avatars 127

11. Blog Posts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131


Blog Post Submission and Display 131
Blog Posts on Profile Pages 134
Paginating Long Blog Post Lists 135
Creating Fake Blog Post Data 135
Rendering Data on Pages 137
Adding a Pagination Widget 138
Rich-Text Posts with Markdown and Flask-PageDown 141
Using Flask-PageDown 141
Handling Rich Text on the Server 143
Permanent Links to Blog Posts 145
Blog Post Editor 146

12. Followers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149


Database Relationships Revisited 149
Many-to-Many Relationships 150
Self-Referential Relationships 151
Advanced Many-to-Many Relationships 152
Followers on the Profile Page 155
Query Followed Posts Using a Database Join 158
Show Followed Posts on the Home Page 160

13. User Comments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165


Database Representation of Comments 165
Comment Submission and Display 167
Comment Moderation 169

14. Application Programming Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175


Introduction to REST 175
Resources Are Everything 176
Request Methods 177
Request and Response Bodies 177
Versioning 178
RESTful Web Services with Flask 179
Creating an API Blueprint 179
Error Handling 180
User Authentication with Flask-HTTPAuth 181
Token-Based Authentication 184
Serializing Resources to and from JSON 186
Implementing Resource Endpoints 188

viii | Table of Contents


Pagination of Large Resource Collections 191
Testing Web Services with HTTPie 192

Part III. The Last Mile


15. Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Obtaining Code Coverage Reports 197
The Flask Test Client 200
Testing Web Applications 200
Testing Web Services 204
End-to-End Testing with Selenium 205
Is It Worth It? 209

16. Performance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211


Logging Slow Database Performance 211
Source Code Profiling 213

17. Deployment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215


Deployment Workflow 215
Logging of Errors During Production 216
Cloud Deployment 217
The Heroku Platform 218
Preparing the Application 218
Testing with Foreman 222
Enabling Secure HTTP with Flask-SSLify 223
Deploying with git push 225
Reviewing Logs 226
Deploying an Upgrade 227
Traditional Hosting 227
Server Setup 227
Importing Environment Variables 228
Setting Up Logging 228

18. Additional Resources. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231


Using an Integrated Development Environment (IDE) 231
Finding Flask Extensions 232
Getting Involved with Flask 232

Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

Table of Contents | ix
Preface

Flask stands out from other frameworks because it lets developers take the driver’s seat
and have full creative control of their applications. Maybe you have heard the phrase
“fighting the framework” before. This happens with most frameworks when you decide
to solve a problem with a solution that isn’t the official one. It could be that you want to
use a different database engine, or maybe a different method of authenticating users.
Deviating from the path set by the framework’s developers will give you lots of
headaches.
Flask is not like that. Do you like relational databases? Great. Flask supports them all.
Maybe you prefer a NoSQL database? No problem at all. Flask works with them too.
Want to use your own homegrown database engine? Don’t need a database at all? Still
fine. With Flask you can choose the components of your application or even write your
own if that is what you want. No questions asked!
The key to this freedom is that Flask was designed from the start to be extended. It comes
with a robust core that includes the basic functionality that all web applications need
and expects the rest to be provided by some of the many third-party extensions in the
ecosystem and, of course, by you.
In this book I present my workflow for developing web applications with Flask. I don’t
claim to have the only true way to build applications with this framework. You should
take my choices as recommendations and not as gospel.
Most software development books provide small and focused code examples that
demonstrate the different features of the target technology in isolation, leaving the “glue”
code that is necessary to transform these different features into a fully working appli‐
cations to be figured out by the reader. I take a completely different approach. All the
examples I present are part of a single application that starts out very simple and is
expanded in each successive chapter. This application begins life with just a few lines of
code and ends as a nicely featured blogging and social networking application.

xi
Who This Book Is For
You should have some level of Python coding experience to make the most of this book.
Although the book assumes no previous Flask knowledge, Python concepts such as
packages, modules, functions, decorators, and object-oriented programming are as‐
sumed to be well understood. Some familiarity with exceptions and diagnosing issues
from stack traces will be very useful.
While working through the examples in this book, you will spend a great deal of time
in the command line. You should feel comfortable using the command line of your
operating system.
Modern web applications cannot avoid the use of HTML, CSS, and JavaScript. The
example application that is developed throughout the book obviously makes use of
these, but the book itself does not go into a lot of detail regarding these technologies
and how they are used. Some degree of familiarity with these languages is recommended
if you intend to develop complete applications without the help of a developer versed
in client-side techniques.
I released the companion application to this book as open source on GitHub. Although
GitHub makes it possible to download applications as regular ZIP or TAR files, I strongly
recommend that you install a Git client and familiarize yourself with source code version
control, at least with the basic commands to clone and check out the different versions
of the application directly from the repository. The short list of commands that you’ll
need is shown in “How to Work with the Example Code ” on page xiii. You will want to
use version control for your own projects as well, so use this book as an excuse to learn
Git!
Finally, this book is not a complete and exhaustive reference on the Flask framework.
Most features are covered, but you should complement this book with the official Flask
documentation.

How This Book Is Organized


This book is divided into three parts:
Part I, Introduction to Flask, explores the basics of web application development with
the Flask framework and some of its extensions:

• Chapter 1 describes the installation and setup of the Flask framework.


• Chapter 2 dives straight into Flask with a basic application.
• Chapter 3 introduces the use of templates in Flask applications.
• Chapter 4 introduces web forms.
• Chapter 5 introduces databases.

xii | Preface
• Chapter 6 introduces email support.
• Chapter 7 presents an application structure that is appropriate for medium and
large applications.

Part II, Example: A Social Blogging Application, builds Flasky, the open source blogging
and social networking application that I developed for this book:

• Chapter 8 implements a user authentication system.


• Chapter 9 implements user roles and permissions.
• Chapter 10 implements user profile pages.
• Chapter 11 creates the blogging interface.
• Chapter 12 implements followers.
• Chapter 13 implements user comments for blog posts.
• Chapter 14 implements an Application Programming Interface (API).

Part III, The Last Mile, describes some important tasks not directly related to application
coding that need to be considered before publishing an application:

• Chapter 15 describes different unit testing strategies in detail.


• Chapter 16 gives an overview of performance analysis techniques.
• Chapter 17 describes deployment options for Flask applications, both traditional
and cloud based.
• Chapter 18 lists additional resources.

How to Work with the Example Code


The code examples presented in this book are available from GitHub at https://
github.com/miguelgrinberg/flasky.
The commit history in this repository was carefully created to match the order in which
concepts are presented in the book. The recommended way to work with the code is to
check out the commits starting from the oldest, then move forward through the commit
list as you make progress with the book. As an alternative, GitHub will also let you
download each commit as a ZIP or TAR file.
If you decide to use Git to work with the source code, then you need to install the Git
client, which you can download from http://git-scm.com. The following command
downloads the example code using Git:
$ git clone https://github.com/miguelgrinberg/flasky.git

Preface | xiii
The git clone command installs the source code from GitHub into a flasky folder that
is created in the current directory. This folder does not contain just source code; a copy
of the Git repository with the entire history of changes made to the application is also
included.
In the first chapter you will be asked to check out the initial release of the application,
and then, at the proper places you will be instructed to move forward in the history.
The Git command that lets you move through the change history is git checkout. Here
is an example:
$ git checkout 1a

The 1a referenced in the command is a tag, a named point in the history of the project.
This repository is tagged according to the chapters of the book, so the 1a tag used in
the example sets the application files to the initial version used in Chapter 1. Most
chapters have more than one tag associated with them, so, for example, tags 5a, 5b, and
so on are incremental versions presented in Chapter 5.
In addition to checking out the source files for a version of the application, you may
need to perform some setup. For example, in some cases you will need to install addi‐
tional Python packages or apply updates to the database. You will be told when these
are necessary.
You will normally not modify the source files of the application, but if you do, then Git
will not let you check out a different revision, as that would cause your local changes to
be lost. Before you can check out a different revision, you will need to revert the files to
their original state. The easiest way to do this is with the git reset command:
$ git reset --hard
This command will destroy your local changes, so you should save anything you don’t
want to lose before you use this command.
From time to time, you may want to refresh your local repository from the one on
GitHub, where bug fixes and improvements may have been applied. The commands
that achieve this are:
$ git fetch --all
$ git fetch --tags
$ git reset --hard origin/master

The git fetch commands are used to update the commit history and the tags in your
local repository from the remote one on GitHub, but none of this affects the actual
source files, which are updated with the git reset command that follows. Once again,
be aware that any time git reset is used you will lose any local changes you have made.
Another useful operation is to view all the differences between two versions of the
application. This can be very useful to understand a change in detail. From the command

xiv | Preface
line, the git diff command can do this. For example, to see the difference between
revisions 2a and 2b, use:
$ git diff 2a 2b
The differences are shown as a patch, which is not a very intuitive format to review
changes if you are not used to working with patch files. You may find that the graphical
comparisons shown by GitHub are much easier to read. For example, the differences
between revisions 2a and 2b can be viewed on GitHub at https://github.com/miguelgrin
berg/flasky/compare/2a...2b

Using Code Examples


This book is here to help you get your job done. In general, if example code is offered
with this book, you may use it in your programs and documentation. You do not need
to contact us for permission unless you’re reproducing a significant portion of the code.
For example, writing a program that uses several chunks of code from this book does
not require permission. Selling or distributing a CD-ROM of examples from O’Reilly
books does require permission. Answering a question by citing this book and quoting
example code does not require permission. Incorporating a significant amount of ex‐
ample code from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title,
author, publisher, and ISBN. For example: “Flask Web Development by Miguel Grinberg
(O’Reilly). Copyright 2014 Miguel Grinberg, 978-1-449-3726-2.”
If you feel your use of code examples falls outside fair use or the permission given above,
feel free to contact us at [email protected].

Conventions Used in This Book


The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant width
Used for program listings, as well as within paragraphs to refer to program elements
such as variable or function names, databases, data types, environment variables,
statements, and keywords.
Constant width bold
Shows commands or other text that should be typed literally by the user.

Preface | xv
Constant width italic
Shows text that should be replaced with user-supplied values or by values deter‐
mined by context.

This element signifies a tip or suggestion.

This element signifies a general note.

This element indicates a warning or caution.

Safari® Books Online


Safari Books Online is an on-demand digital library that
delivers expert content in both book and video form from
the world’s leading authors in technology and business.
Technology professionals, software developers, web designers, and business and crea‐
tive professionals use Safari Books Online as their primary resource for research, prob‐
lem solving, learning, and certification training.
Safari Books Online offers a range of product mixes and pricing programs for organi‐
zations, government agencies, and individuals. Subscribers have access to thousands of
books, training videos, and prepublication manuscripts in one fully searchable database
from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Pro‐
fessional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John
Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT
Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technol‐
ogy, and dozens more. For more information about Safari Books Online, please visit us
online.

xvi | Preface
How to Contact Us
Please address comments and questions concerning this book to the publisher:

O’Reilly Media, Inc.


1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)

We have a web page for this book, where we list errata, examples, and any additional
information. You can access this page at http://www.bit.ly/flask-web-dev.
To comment or ask technical questions about this book, send email to bookques
[email protected].
For more information about our books, courses, conferences, and news, see our website
at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia

Acknowledgments
I could not have written this book alone. I have received a lot of help from family, co-
workers, old friends, and new friends I’ve made along the way.
I’d like to thank Brendan Kohler for his detailed technical review and for his help in
giving shape to the chapter on Application Programming Interfaces. I’m also in debt to
David Baumgold, Todd Brunhoff, Cecil Rock, and Matthew Hugues, who reviewed the
manuscript at different stages of completion and gave me very useful advice regarding
what to cover and how to organize the material.
Writing the code examples for this book was a considerable effort. I appreciate the help
of Daniel Hofmann, who did a thorough code review of the application and pointed out
several improvements. I’m also thankful to my teenage son, Dylan Grinberg, who sus‐
pended his Minecraft addiction for a few weekends and helped me test the code under
several platforms.
O’Reilly has a wonderful program called Early Release that allows impatient readers to
have access to books while they are being written. Some of my Early Release readers
went the extra mile and engaged in useful conversations regarding their experience
working through the book, leading to significant improvements. I’d like to acknowledge

Preface | xvii
Sundeep Gupta, Dan Caron, Brian Wisti and Cody Scott in particular for the contri‐
butions they’ve made to this book.
The staff at O’Reilly Media has always been there for me. Above all I’d like to recognize
my wonderful editor, Meghan Blanchette, for her support, advice, and assistance from
the very first day we met. Meg has made the experience of writing my first book a
memorable one.
To conclude, I would like to give a big thank you to the awesome Flask community.

xviii | Preface
PART I
Introduction to Flask
CHAPTER 1
Installation

Flask is a small framework by most standards, small enough to be called a “micro-


framework.” It is small enough that once you become familiar with it, you will likely be
able to read and understand all of its source code.
But being small does not mean that it does less than other frameworks. Flask was de‐
signed as an extensible framework from the ground up; it provides a solid core with the
basic services, while extensions provide the rest. Because you can pick and choose the
extension packages that you want, you end up with a lean stack that has no bloat and
does exactly what you need.
Flask has two main dependencies. The routing, debugging, and Web Server Gateway
Interface (WSGI) subsystems come from Werkzeug, while template support is provided
by Jinja2. Werkzeug and Jinja2 are authored by the core developer of Flask.
There is no native support in Flask for accessing databases, validating web forms, au‐
thenticating users, or other high-level tasks. These and many other key services most
web applications need are available through extensions that integrate with the core
packages. As a developer, you have the power to cherry-pick the extensions that work
best for your project or even write your own if you feel inclined to. This is in contrast
with a larger framework, where most choices have been made for you and are hard or
sometimes impossible to change.
In this chapter, you will learn how to install Flask. The only requirement you need is a
computer with Python installed.

The code examples in this book have been verified to work with
Python 2.7 and Python 3.3, so using one of these two versions is
strongly recommended.

3
Using Virtual Environments
The most convenient way to install Flask is to use a virtual environment. A virtual
environment is a private copy of the Python interpreter onto which you can install
packages privately, without affecting the global Python interpreter installed in your
system.
Virtual environments are very useful because they prevent package clutter and version
conflicts in the system’s Python interpreter. Creating a virtual environment for each
application ensures that applications have access to only the packages that they use,
while the global interpreter remains neat and clean and serves only as a source from
which more virtual environments can be created. As an added benefit, virtual environ‐
ments don’t require administrator rights.
Virtual environments are created with the third-party virtualenv utility. To check
whether you have it installed in your system, type the following command:
$ virtualenv --version
If you get an error, you will have to install the utility.

Python 3.3 adds native support of virtual environments through the


venv module and the pyvenv command. pyvenv can be used instead
of virtualenv, but note that virtual environments created with py‐
venv on Python 3.3 do not include pip, which needs to be installed
manually. This limitation has been removed in Python 3.4, where
pyvenv can be used as a complete virtualenv replacement.

Most Linux distributions provide a package for virtualenv. For example, Ubuntu users
can install it with this command:
$ sudo apt-get install python-virtualenv
If you are using Mac OS X, then you can install virtualenv using easy_install:
$ sudo easy_install virtualenv
If you are using Microsoft Windows or any operating system that does not provide an
official virtualenv package, then you have a slightly more complicated install procedure.
Using your web browser, navigate to https://bitbucket.org/pypa/setuptools, the home of
the setuptools installer. In that page, look for a link to download the installer script.
This is a script called ez_setup.py. Save this file to a temporary folder on your computer,
then run the following commands in that folder:
$ python ez_setup.py
$ easy_install virtualenv

4 | Chapter 1: Installation
The previous commands must be issued from an account with ad‐
ministrator rights. On Microsoft Windows, start the command
prompt window using the “Run as Administrator” option. On Unix-
based systems, the two installation commands must be preceded with
sudo or executed as the root user. Once installed, the virtualenv util‐
ity can be invoked from regular accounts.

Now you need to create the folder that will host the example code, which is available
from a GitHub repository. As discussed in “How to Work with the Example Code ” on
page xiii, the most convenient way to do this is by checking out the code directly from
GitHub using a Git client. The following commands download the example code from
GitHub and initialize the application folder to version “1a,” the initial version of the
application:
$ git clone https://github.com/miguelgrinberg/flasky.git
$ cd flasky
$ git checkout 1a
The next step is to create the Python virtual environment inside the flasky folder using
the virtualenv command. This command has a single required argument: the name of
the virtual environment. A folder with the chosen name will be created in the current
directory and all files associated with the virtual environment will be inside. A com‐
monly used naming convention for virtual environments is to call them venv:
$ virtualenv venv
New python executable in venv/bin/python2.7
Also creating executable in venv/bin/python
Installing setuptools............done.
Installing pip...............done.
Now you have a venv folder inside the flasky folder with a brand-new virtual environ‐
ment that contains a private Python interpreter. To start using the virtual environment,
you have to “activate” it. If you are using a bash command line (Linux and Mac OS X
users), you can activate the virtual environment with this command:
$ source venv/bin/activate
If you are using Microsoft Windows, the activation command is:
$ venv\Scripts\activate
When a virtual environment is activated, the location of its Python interpreter is added
to the PATH, but this change is not permanent; it affects only your current command
session. To remind you that you have activated a virtual environment, the activation
command modifies the command prompt to include the name of the environment:
(venv) $

Using Virtual Environments | 5


When you are done working with the virtual environment and want to return to the
global Python interpreter, type deactivate at the command prompt.

Installing Python Packages with pip


Most Python packages are installed with the pip utility, which virtualenv automatically
adds to all virtual environments upon creation. When a virtual environment is activated,
the location of the pip utility is added to the PATH.

If you created the virtual environment with pyvenv under Python 3.3,
then pip must be installed manually. Installation instructions are
available on the pip website. Under Python 3.4, pyvenv installs pip
automatically.

To install Flask into the virtual environment, use the following command:
(venv) $ pip install flask
With this command, Flask and its dependencies are installed in the virtual environment.
You can verify that Flask was installed correctly by starting the Python interpreter and
trying to import it:
(venv) $ python
>>> import flask
>>>
If no errors appear, you can congratulate yourself: you are ready for the next chapter,
where you will write your first web application.

6 | Chapter 1: Installation
CHAPTER 2
Basic Application Structure

In this chapter, you will learn about the different parts of a Flask application. You will
also write and run your first Flask web application.

Initialization
All Flask applications must create an application instance. The web server passes all
requests it receives from clients to this object for handling, using a protocol called Web
Server Gateway Interface (WSGI). The application instance is an object of class Flask,
usually created as follows:
from flask import Flask
app = Flask(__name__)

The only required argument to the Flask class constructor is the name of the main
module or package of the application. For most applications, Python’s __name__ variable
is the correct value.

The name argument that is passed to the Flask application construc‐


tor is a source of confusion among new Flask developers. Flask uses
this argument to determine the root path of the application so that it
later can find resource files relative to the location of the application.

Later you will see more complex examples of application initialization, but for simple
applications this is all that is needed.

7
Routes and View Functions
Clients such as web browsers send requests to the web server, which in turn sends them
to the Flask application instance. The application instance needs to know what code
needs to run for each URL requested, so it keeps a mapping of URLs to Python functions.
The association between a URL and the function that handles it is called a route.
The most convenient way to define a route in a Flask application is through the
app.route decorator exposed by the application instance, which registers the decorated
function as a route. The following example shows how a route is declared using this
decorator:
@app.route('/')
def index():
return '<h1>Hello World!</h1>'

Decorators are a standard feature of the Python language; they can


modify the behavior of a function in different ways. A common pat‐
tern is to use decorators to register functions as handlers for an event.

The previous example registers the function index() as the handler for the application’s
root URL. If this application were deployed on a server associated with the www.ex‐
ample.com domain name, then navigating to http://www.example.com on your browser
would trigger index() to run on the server. The return value of this function, called the
response, is what the client receives. If the client is a web browser, the response is the
document that is displayed to the user.
Functions like index() are called view functions. A response returned by a view function
can be a simple string with HTML content, but it can also take more complex forms, as
you will see later.

Response strings embedded in Python code lead to code that is dif‐


ficult to maintain, and it is done here only to introduce the concept
of responses. You will learn the proper way to generate responses in
Chapter 3.

If you pay attention to how some URLs for services that you use every day are formed,
you will notice that many have variable sections. For example, the URL for your Face‐
book profile page is http://www.facebook.com/<your-name>, so your username is part
of it. Flask supports these types of URLs using a special syntax in the route decorator.
The following example defines a route that has a dynamic name component:

8 | Chapter 2: Basic Application Structure


@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' % name
The portion enclosed in angle brackets is the dynamic part, so any URLs that match the
static portions will be mapped to this route. When the view function is invoked, Flask
sends the dynamic component as an argument. In the earlier example view function,
this argument is used to generate a personalized greeting as a response.
The dynamic components in routes are strings by default but can also be defined with
a type. For example, route /user/<int:id> would match only URLs that have an integer
in the id dynamic segment. Flask supports types int, float, and path for routes. The
path type also represents a string but does not consider slashes as separators and instead
considers them part of the dynamic component.

Server Startup
The application instance has a run method that launches Flask’s integrated development
web server:
if __name__ == '__main__':
app.run(debug=True)

The __name__ == '__main__' Python idiom is used here to ensure that the develop‐
ment web server is started only when the script is executed directly. When the script is
imported by another script, it is assumed that the parent script will launch a different
server, so the app.run() call is skipped.
Once the server starts up, it goes into a loop that waits for requests and services them.
This loop continues until the application is stopped, for example by hitting Ctrl-C.
There are several option arguments that can be given to app.run() to configure the
mode of operation of the web server. During development, it is convenient to enable
debug mode, which among other things activates the debugger and the reloader. This is
done by passing the argument debug set to True.

The web server provided by Flask is not intended for production use.
You will learn about production web servers in Chapter 17.

A Complete Application
In the previous sections, you learned about the different parts of a Flask web application,
and now it is time to write one. The entire hello.py application script is nothing more

Server Startup | 9
than the three parts described earlier combined in a single file. The application is shown
in Example 2-1.
Example 2-1. hello.py: A complete Flask application
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
return '<h1>Hello World!</h1>'

if __name__ == '__main__':
app.run(debug=True)

If you have cloned the application’s Git repository on GitHub, you can
now run git checkout 2a to check out this version of the application.

To run the application, make sure that the virtual environment you created earlier is
activated and has Flask installed. Now open your web browser and type http://
127.0.0.1:5000/ in the address bar. Figure 2-1 shows the web browser after connecting
to the application.

Figure 2-1. hello.py Flask application

Then launch the application with the following command:

10 | Chapter 2: Basic Application Structure


(venv) $ python hello.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
If you type any other URL, the application will not know how to handle it and will return
an error code 404 to the browser—the familiar error that you get when you navigate to
a web page that does not exist.
The enhanced version of the application shown in Example 2-2 adds a second route that
is dynamic. When you visit this URL, you are presented with a personalized greeting.
Example 2-2. hello.py: Flask application with a dynamic route
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
return '<h1>Hello World!</h1>'

@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' % name

if __name__ == '__main__':
app.run(debug=True)

If you have cloned the application’s Git repository on GitHub, you can
now run git checkout 2b to check out this version of the application.

To test the dynamic route, make sure the server is running and then navigate to http://
localhost:5000/user/Dave. The application will respond with a customized greeting,
generated using the name dynamic argument. Try different names to see how the view
function always generates the response based on the name given. An example is shown
in Figure 2-2.

A Complete Application | 11
Figure 2-2. Dynamic route

The Request-Response Cycle


Now that you have played with a basic Flask application, you might want to know more
about how Flask works its magic. The following sections describe some of the design
aspects of the framework.

Application and Request Contexts


When Flask receives a request from a client, it needs to make a few objects available to
the view function that will handle it. A good example is the request object, which en‐
capsulates the HTTP request sent by the client.
The obvious way in which Flask could give a view function access to the request object
is by sending it as an argument, but that would require every single view function in the
application to have an extra argument. Things get more complicated if you consider
that the request object is not the only object that view functions might need to access
to fulfill a request.
To avoid cluttering view functions with lots of arguments that may or may not be needed,
Flask uses contexts to temporarily make certain objects globally accessible. Thanks to
contexts, view functions like the following one can be written:
from flask import request

@app.route('/')
def index():

12 | Chapter 2: Basic Application Structure


user_agent = request.headers.get('User-Agent')
return '<p>Your browser is %s</p>' % user_agent

Note how in this view function request is used as if it was a global variable. In reality,
request cannot be a global variable if you consider that in a multithreaded server the
threads are working on different requests from different clients at the same time, so
each thread needs to see a different object in request. Contexts enable Flask to make
certain variables globally accessible to a thread without interfering with the other
threads.

A thread is the smallest sequence of instructions that can be man‐


aged independently. It is common for a process to have multiple ac‐
tive threads, sometimes sharing resources such as memory or file
handles. Multithreaded web servers start a pool of threads and se‐
lect a thread from the pool to handle each incoming request.

There are two contexts in Flask: the application context and the request context. Table 2-1
shows the variables exposed by each of these contexts.
Table 2-1. Flask context globals
Variable name Context Description
current_app Application context The application instance for the active application.
g Application context An object that the application can use for temporary storage during the handling of
a request. This variable is reset with each request.
request Request context The request object, which encapsulates the contents of a HTTP request sent by the
client.
session Request context The user session, a dictionary that the application can use to store values that are
“remembered” between requests.

Flask activates (or pushes) the application and request contexts before dispatching a
request and then removes them when the request is handled. When the application
context is pushed, the current_app and g variables become available to the thread;
likewise, when the request context is pushed, request and session become available
as well. If any of these variables are accessed without an active application or request
context, an error is generated. The four context variables will be revisited in later chap‐
ters in detail, so don’t worry if you don’t understand why they are useful yet.
The following Python shell session demonstrates how the application context works:
>>> from hello import app
>>> from flask import current_app
>>> current_app.name
Traceback (most recent call last):
...
RuntimeError: working outside of application context

The Request-Response Cycle | 13


>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>> current_app.name
'hello'
>>> app_ctx.pop()

In this example, current_app.name fails when there is no application context active but
becomes valid once a context is pushed. Note how an application context is obtained
by invoking app.app_context() on the application instance.

Request Dispatching
When the application receives a request from a client, it needs to find what view function
to invoke to service it. For this task, Flask looks up the URL given in the request in the
application’s URL map, which contains a mapping of URLs to the view functions that
handle them. Flask builds this map using the app.route decorators or the equivalent
nondecorator version app.add_url_rule().
To see what the URL map in a Flask application looks like, you can inspect the map
created for hello.py in the Python shell. For this test, make sure that your virtual envi‐
ronment is activated:
(venv) $ python
>>> from hello import app
>>> app.url_map
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/user/<name>' (HEAD, OPTIONS, GET) -> user>])

The / and /user/<name> routes were defined by the app.route decorators in the ap‐
plication. The /static/<filename> route is a special route added by Flask to give access
to static files. You will learn more about static files in Chapter 3.
The HEAD, OPTIONS, GET elements shown in the URL map are the request methods that
are handled by the route. Flask attaches methods to each route so that different request
methods sent to the same URL can be handled by different view functions. The HEAD
and OPTIONS methods are managed automatically by Flask, so in practice it can be said
that in this application the three routes in the URL map are attached to the GET method.
You will learn about specifying different request methods for routes in Chapter 4.

Request Hooks
Sometimes it is useful to execute code before or after each request is processed. For
example, at the start of each request it may be necessary to create a database connection,
or authenticate the user making the request. Instead of duplicating the code that does
this in every view function, Flask gives you the option to register common functions to
be invoked before or after a request is dispatched to a view function.

14 | Chapter 2: Basic Application Structure


Request hooks are implemented as decorators. These are the four hooks supported by
Flask:

• before_first_request: Register a function to run before the first request is


handled.
• before_request: Register a function to run before each request.
• after_request: Register a function to run after each request, if no unhandled ex‐
ceptions occurred.
• teardown_request: Register a function to run after each request, even if unhandled
exceptions occurred.

A common pattern to share data between request hook functions and view functions is
to use the g context global. For example, a before_request handler can load the logged-
in user from the database and store it in g.user. Later, when the view function is invoked,
it can access the user from there.
Examples of request hooks will be shown in future chapters, so don’t worry if this does
not quite make sense yet.

Responses
When Flask invokes a view function, it expects its return value to be the response to the
request. In most cases the response is a simple string that is sent back to the client as an
HTML page.
But the HTTP protocol requires more than a string as a response to a request. A very
important part of the HTTP response is the status code, which Flask by default sets to
200, the code that indicates that the request was carried out successfully.
When a view function needs to respond with a different status code, it can add the
numeric code as a second return value after the response text. For example, the following
view function returns a 400 status code, the code for a bad request error:
@app.route('/')
def index():
return '<h1>Bad Request</h1>', 400
Responses returned by view functions can also take a third argument, a dictionary of
headers that are added to the HTTP response. This is rarely needed, but you will see an
example in Chapter 14.
Instead of returning one, two, or three values as a tuple, Flask view functions have the
option of returning a Response object. The make_response() function takes one, two,
or three arguments, the same values that can be returned from a view function, and
returns a Response object. Sometimes it is useful to perform this conversion inside the

The Request-Response Cycle | 15


view function and then use the methods of the response object to further configure the
response. The following example creates a response object and then sets a cookie in it:

from flask import make_response

@app.route('/')
def index():
response = make_response('<h1>This document carries a cookie!</h1>')
response.set_cookie('answer', '42')
return response
There is a special type of response called a redirect. This response does not include a
page document; it just gives the browser a new URL from which to load a new page.
Redirects are commonly used with web forms, as you will learn in Chapter 4.
A redirect is typically indicated with a 302 response status code and the URL to redirect
to given in a Location header. A redirect response can be generated using a three-value
return, or also with a Response object, but given its frequent use, Flask provides a
redirect() helper function that creates this response:
from flask import redirect

@app.route('/')
def index():
return redirect('http://www.example.com')

Another special response is issued with the abort function, which is used for error
handling. The following example returns status code 404 if the id dynamic argument
given in the URL does not represent a valid user:
from flask import abort

@app.route('/user/<id>')
def get_user(id):
user = load_user(id)
if not user:
abort(404)
return '<h1>Hello, %s</h1>' % user.name

Note that abort does not return control back to the function that calls it but gives control
back to the web server by raising an exception.

Flask Extensions
Flask is designed to be extended. It intentionally stays out of areas of important func‐
tionality such as database and user authentication, giving you the freedom to select the
packages that fit your application the best, or to write your own if you so desire.

16 | Chapter 2: Basic Application Structure


There is a large variety of extensions for many different purposes that were created by
the community, and if that is not enough, any standard Python package or library can
be used as well. To give you an idea of how an extension is incorporated into an appli‐
cation, the following section adds an extension to hello.py that enhances the application
with command-line arguments.

Command-Line Options with Flask-Script


Flask’s development web server supports a number of startup configuration options,
but the only way to specify them is by passing them as arguments to the app.run() call
in the script. This is not very convenient; the ideal way to pass configuration options is
through command-line arguments.
Flask-Script is an extension for Flask that adds a command-line parser to your Flask
application. It comes packaged with a set of general-purpose options and also supports
custom commands.
The extension is installed with pip:
(venv) $ pip install flask-script
Example 2-3 shows the changes needed to add command-line parsing to the hello.py
application.
Example 2-3. hello.py: Using Flask-Script
from flask.ext.script import Manager
manager = Manager(app)

# ...

if __name__ == '__main__':
manager.run()

Extensions developed specifically for Flask are exposed under the flask.ext name‐
space. Flask-Script exports a class named Manager, which is imported from
flask.ext.script.
The method of initialization of this extension is common to many extensions: an in‐
stance of the main class is initialized by passing the application instance as an argument
to the constructor. The created object is then used as appropriate for each extension. In
this case, the server startup is routed through manager.run(), where the command line
is parsed.

Flask Extensions | 17
If you have cloned the application’s Git repository on GitHub, you can
run git checkout 2c to check out this version of the application.

With these changes, the application acquires a basic set of command-line options. Run‐
ning hello.py now shows a usage message:
$ python hello.py
usage: hello.py [-h] {shell,runserver} ...

positional arguments:
{shell,runserver}
shell Runs a Python shell inside Flask application context.
runserver Runs the Flask development server i.e. app.run()

optional arguments:
-h, --help show this help message and exit

The shell command is used to start a Python shell session in the context of the appli‐
cation. You can use this session to run maintenance tasks or tests, or to debug issues.
The runserver command, as its name implies, starts the web server. Running python
hello.py runserver starts the web server in debug mode, but there many more options
available:
(venv) $ python hello.py runserver --help
usage: hello.py runserver [-h] [-t HOST] [-p PORT] [--threaded]
[--processes PROCESSES] [--passthrough-errors] [-d]
[-r]

Runs the Flask development server i.e. app.run()

optional arguments:
-h, --help show this help message and exit
-t HOST, --host HOST
-p PORT, --port PORT
--threaded
--processes PROCESSES
--passthrough-errors
-d, --no-debug
-r, --no-reload

The --host argument is a useful option because it tells the web server what network
interface to listen to for connections from clients. By default, Flask’s development web
server listens for connections on localhost, so only connections originating from
within the computer running the server are accepted. The following command makes
the web server listen for connections on the public network interface, enabling other
computers in the network to connect as well:

18 | Chapter 2: Basic Application Structure


(venv) $ python hello.py runserver --host 0.0.0.0
* Running on http://0.0.0.0:5000/
* Restarting with reloader
The web server should now be accessible from any computer in the network at http://
a.b.c.d:5000, where “a.b.c.d” is the external IP address of the computer running the
server.
This chapter introduced the concept of responses to requests, but there is a lot more to
say about responses. Flask provides very good support for generating responses using
templates, and this is such an important topic that the next chapter is dedicated to it.

Flask Extensions | 19
CHAPTER 3
Templates

The key to writing applications that are easy to maintain is to write clean and well-
structured code. The examples that you have seen so far are too simple to demonstrate
this, but Flask view functions have two completely independent purposes disguised as
one, which creates a problem.
The obvious task of a view function is to generate a response to a request, as you have
seen in the examples shown in Chapter 2. For the simplest requests this is enough, but
in general a request triggers a change in the state of the application, and the view function
is also where this change is generated.
For example, consider a user who is registering a new account on a website. The user
types an email address and a password in a web form and clicks the Submit button. On
the server, a request that includes the data from the user arrives and Flask dispatches it
to the view function that handles registration requests. This view function needs to talk
to the database to get the new user added and then generate a response to send back to
the browser. These two types of tasks are formally called business logic and presentation
logic, respectively.
Mixing business and presentation logic leads to code that is hard to understand and
maintain. Imagine having to build the HTML code for a large table by concatenating
data obtained from the database with the necessary HTML string literals. Moving the
presentation logic into templates helps improve the maintainability of the application.
A template is a file that contains the text of a response, with placeholder variables for
the dynamic parts that will be known only in the context of a request. The process that
replaces the variables with actual values and returns a final response string is called
rendering. For the task of rendering templates, Flask uses a powerful template engine
called Jinja2.

21
The Jinja2 Template Engine
In its simplest form, a Jinja2 template is a file that contains the text of a response.
Example 3-1 shows a Jinja2 template that matches the response of the index() view
function of Example 2-1.
Example 3-1. templates/index.html: Jinja2 template
<h1>Hello World!</h1>

The response returned by view function user() of Example 2-2 has a dynamic com‐
ponent, which is represented by a variable. Example 3-2 shows the template that im‐
plements this response.
Example 3-2. templates/user.html: Jinja2 template
<h1>Hello, {{ name }}!</h1>

Rendering Templates
By default Flask looks for templates in a templates subfolder located inside the applica‐
tion folder. For the next version of hello.py, you need to store the templates defined
earlier in a new templates folder as index.html and user.html.
The view functions in the application need to be modified to render these templates.
Example 3-3 shows these changes.
Example 3-3. hello.py: Rendering a template
from flask import Flask, render_template

# ...

@app.route('/index')
def index():
return render_template('index.html')

@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)

The function render_template provided by Flask integrates the Jinja2 template engine
with the application. This function takes the filename of the template as its first argu‐
ment. Any additional arguments are key/value pairs that represent actual values for
variables referenced in the template. In this example, the second template is receiving
a name variable.
Keyword arguments like name=name in the previous example are fairly common but may
seem confusing and hard to understand if you are not used to them. The “name” on the

22 | Chapter 3: Templates
left side represents the argument name, which is used in the placeholder written in the
template. The “name” on the right side is a variable in the current scope that provides
the value for the argument of the same name.

If you have cloned the application’s Git repository on GitHub, you can
run git checkout 3a to check out this version of the application.

Variables
The {{ name }} construct used in the template shown in Example 3-2 references a
variable, a special placeholder that tells the template engine that the value that goes in
that place should be obtained from data provided at the time the template is rendered.
Jinja2 recognizes variables of any type, even complex types such as lists, dictionaries
and objects. The following are some more examples of variables used in templates:
<p>A value from a dictionary: {{ mydict['key'] }}.</p>
<p>A value from a list: {{ mylist[3] }}.</p>
<p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>
<p>A value from an object's method: {{ myobj.somemethod() }}.</p>
Variables can be modified with filters, which are added after the variable name with a
pipe character as separator. For example, the following template shows the name variable
capitalized:
Hello, {{ name|capitalize }}
Table 3-1 lists some of the commonly used filters that come with Jinja2.
Table 3-1. Jinja2 variable filters
Filter name Description
safe Renders the value without applying escaping
capitalize Converts the first character of the value to uppercase and the rest to lowercase
lower Converts the value to lowercase characters
upper Converts the value to uppercase characters
title Capitalizes each word in the value
trim Removes leading and trailing whitespace from the value
striptags Removes any HTML tags from the value before rendering

The safe filter is interesting to highlight. By default Jinja2 escapes all variables for se‐
curity purposes. For example, if a variable is set to the value '<h1>Hello</h1>', Jinja2

The Jinja2 Template Engine | 23


will render the string as '&lt;h1&gt;Hello&lt;/h1&gt;', which will cause the h1 ele‐
ment to be displayed and not interpreted by the browser. Many times it is necessary to
display HTML code stored in variables, and for those cases the safe filter is used.

Never use the safe filter on values that aren’t trusted, such as text
entered by users on web forms.

The complete list of filters can be obtained from the official Jinja2 documentation.

Control Structures
Jinja2 offers several control structures that can be used to alter the flow of the template.
This section introduces some of the most useful ones with simple examples.
The following example shows how conditional statements can be entered in a template:
{% if user %}
Hello, {{ user }}!
{% else %}
Hello, Stranger!
{% endif %}
Another common need in templates is to render a list of elements. This example shows
how this can be done with a for loop:
<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>
Jinja2 also supports macros, which are similar to functions in Python code. For example:
{% macro render_comment(comment) %}
<li>{{ comment }}</li>
{% endmacro %}

<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>
To make macros more reusable, they can be stored in standalone files that are then
imported from all the templates that need them:
{% import 'macros.html' as macros %}
<ul>

24 | Chapter 3: Templates
{% for comment in comments %}
{{ macros.render_comment(comment) }}
{% endfor %}
</ul>
Portions of template code that need to be repeated in several places can be stored in a
separate file and included from all the templates to avoid repetition:
{% include 'common.html' %}
Yet another powerful way to reuse is through template inheritance, which is similar to
class inheritance in Python code. First, a base template is created with the name
base.html:
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Application</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

Here the block tags define elements that a derived template can change. In this example,
there are blocks called head, title, and body; note that title is contained by head. The
following example is a derived template of the base template:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}

The extends directive declares that this template derives from base.html. This directive
is followed by new definitions for the three blocks defined in the base template, which
are inserted in the proper places. Note that the new definition of the head block, which
is not empty in the base template, uses super() to retain the original contents.
Real-world usage of all the control structures presented in this section will be shown
later, so you will have the opportunity to see how they work.

The Jinja2 Template Engine | 25


Twitter Bootstrap Integration with Flask-Bootstrap
Bootstrap is an open source framework from Twitter that provides user interface com‐
ponents to create clean and attractive web pages that are compatible with all modern
web browsers.
Bootstrap is a client-side framework, so the server is not directly involved with it. All
the server needs to do is provide HTML responses that reference Bootstrap’s cascading
style sheets (CSS) and JavaScript files and instantiate the desired components through
HTML, CSS, and JavaScript code. The ideal place to do all this is in templates.
The obvious way to integrate Bootstrap with the application is to make all the necessary
changes to the templates. A simpler approach is to use a Flask extension called Flask-
Bootstrap to simplify the integration effort. Flask-Bootstrap can be installed with pip:
(venv) $ pip install flask-bootstrap
Flask extensions are usually initialized at the same time the application instance is cre‐
ated. Example 3-4 shows the initialization of Flask-Bootstrap.
Example 3-4. hello.py: Flask-Bootstrap initialization
from flask.ext.bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)

Like Flask-Script in Chapter 2, Flask-Bootstrap is imported from the flask.ext name‐


space and initialized by passing the application instance in the constructor.
Once Flask-Bootstrap is initialized, a base template that includes all the Bootstrap files
is available to the application. This template takes advantage of Jinja2’s template inher‐
itance; the application extends a base template that has the general structure of the page
including the elements that import Bootstrap. Example 3-5 shows a new version of
user.html as a derived template.
Example 3-5. templates/user.html: Template that uses Flask-Bootstrap
{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>

26 | Chapter 3: Templates
</button>
<a class="navbar-brand" href="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}

{% block content %}
<div class="container">
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
</div>
{% endblock %}

The Jinja2 extends directive implements the template inheritance by referencing boot‐
strap/base.html from Flask-Bootstrap. The base template from Flask-Bootstrap provides
a skeleton web page that includes all the Bootstrap CSS and JavaScript files.
Base templates define blocks that can be overriden by derived templates. The block and
endblock directives define blocks of content that are added to the base template.
The user.html template above defines three blocks called title, navbar, and content.
These are all blocks that the base template exports for derived templates to define. The
title block is straightforward; its contents will appear between <title> tags in the
header of the rendered HTML document. The navbar and content blocks are reserved
for the page navigation bar and main content.
In this template, the navbar block defines a simple navigation bar using Bootstrap com‐
ponents. The content block has a container <div> with a page header inside. The greet‐
ing line that was in the previous version of the template is now inside the page header.
Figure 3-1 shows how the application looks with these changes.

If you have cloned the application’s Git repository on GitHub, you can
run git checkout 3b to check out this version of the application.
The Bootstrap official documentation is a great learning resource full
of copy/paste-ready examples.

Twitter Bootstrap Integration with Flask-Bootstrap | 27


Figure 3-1. Twitter Bootstrap templates

Flask-Bootstrap’s base.html template defines several other blocks that can be used in
derived templates. Table 3-2 shows the complete list of available blocks.
Table 3-2. Flask-Bootstrap’s base template blocks
Block name Description
doc The entire HTML document
html_attribs Attributes inside the <html> tag
html The contents of the <html> tag
head The contents of the <head> tag
title The contents of the <title> tag
metas The list of <meta> tags
styles Cascading stylesheet definitions
body_attribs Attributes inside the <body> tag
body The contents of the <body> tag
navbar User-defined navigation bar
content User-defined page content
scripts JavaScript declarations at the bottom of the document

Many of the blocks in Table 3-2 are used by Flask-Bootstrap itself, so overriding them
directly would cause problems. For example, the styles and scripts blocks are where
the Bootstrap files are declared. If the application needs to add its own content to a block
that already has some content, then Jinja2’s super() function must be used. For example,

28 | Chapter 3: Templates
this is how the scripts block would need to be written in the derived template to add
a new JavaScript file to the document:
{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}

Custom Error Pages


When you enter an invalid route in your browser’s address bar, you get a code 404 error
page. The error page is now too plain and unattractive, and it has no consistency with
the page that uses Bootstrap.
Flask allows an application to define custom error pages that can be based on templates,
like regular routes. The two most common error codes are 404, triggered when the client
requests a page or route that is not known, and 500, triggered when there is an unhandled
exception. Example 3-6 shows how to provide custom handlers for these two errors.
Example 3-6. hello.py: Custom error pages
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500

Error handlers return a response, like view functions. They also return the numeric
status code that corresponds to the error.
The templates referenced in the error handlers need to be written. These templates
should follow the same layout of the regular pages, so in this case they will have a
navigation bar and a page header that shows the error message.
The straightforward way to write these templates is to copy templates/user.html to
templates/404.html and templates/500.html and then change the page header element
in these two new files to the appropriate error message, but this will generate a lot of
duplication.
Jinja2’s template inheritance can help with this. In the same way Flask-Bootstrap pro‐
vides a base template with the basic layout of the page, the application can define its
own base template with a more complete page layout that includes the navigation bar
and leaves the page content to be defined in derived templates. Example 3-7 shows
templates/base.html, a new template that inherits from bootstrap/base.html and defines
the navigation bar, but is itself a base template to other templates such as templates/
user.html, templates/404.html, and templates/500.html.

Custom Error Pages | 29


Example 3-7. templates/base.html: Base application template with navigation bar
{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}

{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}

In the content block of this template is just a container <div> element that wraps a new
empty block called page_content, which derived templates can define.
The templates of the application will now inherit from this template instead of directly
from Flask-Bootstrap. Example 3-8 shows how simple it is to construct a custom code
404 error page that inherits from templates/base.html.
Example 3-8. templates/404.html: Custom code 404 error page using template inheri‐
tance
{% extends "base.html" %}

{% block title %}Flasky - Page Not Found{% endblock %}

{% block page_content %}
<div class="page-header">
<h1>Not Found</h1>

30 | Chapter 3: Templates
Exploring the Variety of Random
Documents with Different Content
I was introduced to the Medical Director, and he showed me round, omitting
one wing, in which he told me there were a couple of cases of plague. I
happened to know that there were really about a dozen, so I readily agreed
that that part should be left out.
As prison hospital, it differed very little from others that I had seen in
England. There was the same neatness and exquisite cleanliness everywhere,
though the wards were somewhat darker, and therefore cooler, which, with
the midday sun at 106° in the shade, was not a bad thing. All the nurses
were, of course, Sisters of Mercy.[3] In fact, practically all the nursing in New
Caledonia is done by Sisters, and not a few of these heroic women had
become brides of the Black Death before I left.
Here, as in all other prison hospitals I have visited, diet, stimulants, and
medicine are absolutely at the discretion of the Director. No matter what the
cost, the spark of life must be kept alive as long as possible in the breast of
the murderer, the forger, and the thief, or the criminal whose light of reason
has already been quenched in the darkness of the Black Cell.
In fact, so careful are the authorities of their patients’ general health that
they give them nothing in the way of meat but the best beef and mutton that
can be imported from Australia; Caledonian fed meat is not considered
nourishing enough. In normal times the death-rate of Ile Nou, which is wholly
given over to convict camps, is two or three per cent. lower than that of the
town of Noumea.
Part of the Hospital Buildings, Ile Nou. The roofed-terrace in front is where the patients take
their siesta in the middle of the day. One of these is attached to each court of the Hospital.
Some of the mattresses may be seen to the right.

Then from this little flowery paradise of rest and quietness we went across
the road to another enclosure in which there were two long, white buildings, a
prison and a row of offices, at right angles to each other. This was the “bad”
side. On the other there had been invalids and invalid lunatics; here there
were only lunatics, and mostly dangerous at that—men who, after being
criminals, had become madmen; not like the dwellers in Broadmoor, who are
only criminal because they are mad.
I once paid a visit to the worst part of the men’s side at Broadmoor, but I
don’t think it was quite as bad as the long corridor which led through that
gruesome home of madness. On either hand were heavy black-painted, iron
doors, and inside these a hinged grating through which the prisoner could be
fed.
The cells were about nine feet by six feet. They had neither furniture nor
bedclothes in them. The furniture would have been smashed up either in
sheer wanton destruction or for use as missiles to hurl through the grating,
and the bedclothes would have been torn up into strips for hanging or
strangling purposes.
It has been my good or bad luck to see poor humanity in a good many
shapes and guises, but I never saw such a series of pitiful parodies of
manhood as I saw when those cell doors were opened.
Some were crouched down in the corners of their cells, muttering to
themselves and picking the sacking in which they were clothed to pieces,
thread by thread. It was no use giving them regular prison clothing, for they
would pick themselves naked in a couple of days. Others were walking up and
down the narrow limits of their cells, staring with horribly vacant eyes at the
roof or the floor, and not taking the slightest notice of us.
One man was lying down scraping with bleeding fingers at the black
asphalted floor under the impression that he was burrowing his way to
freedom; others were sitting or lying on the floor motionless as death; and
others sprang at the bars like wild beasts the moment the door was opened.
But the most horrible sight I saw during that very bad quarter of an hour
was a gaunt-faced, square-built man of middle-height who got up out of a
corner as his cell door opened, and stood in the middle facing us.
He never moved a muscle, or winked an eyelid. His eyes looked at us with
the steady, burning stare of hate and ferocity. His lips were drawn back from
his teeth like the lips of an ape in a rage, and his hands were half clenched
like claws. The man was simply the incarnation of madness, savagery, and
despair. He had gone mad in the Black Cell, and the form that his madness
had taken was the belief that nothing would nourish him but human flesh. Of
course he had to be fed by force.
When we got outside a big warder pulled up his jumper and showed me the
marks of two rows of human teeth in his side. If another man hadn’t stunned
the poor wretch with the butt of his revolver he would have bitten the piece
clean out—after which I was glad when the Doctor suggested that I should go
to his quarters and have a drink with him.

V
A CONVICT ARCADIA

I visited two or three other industrial camps and the farm-settlements


before I left Ile Nou, but as I had yet to go through the agricultural portions
of the colony it would be no use taking up space in describing them here.
There are practically no roads to speak of in New Caledonia outside a short
strip of the south-western coast. In September, 1863, Napoleon the Little
signed the decree which converted the virgin paradise of New Caledonia into a
hell of vice and misery—a description which is perhaps somewhat strong, but
which history has amply justified. In the following year the transport Iphigénie
took a cargo of two hundred and forty-eight galley-slaves from Toulon and
landed them where the town of Noumea now stands. This consignment was
added to by rapidly following transports, and for thirty years at least the
administration of New Caledonia has had at its disposal an average of from
seven to ten thousand able-bodied criminals for purposes of general
improvement, and more especially for the preparation of the colony for that
free colonisation which has been the dream of so many ministers and
governors.
Now the area of New Caledonia is, roughly speaking, between six thousand
and seven thousand square miles, and after an occupation of nearly forty
years it has barely fifty miles of roads over which a two-wheeled vehicle can
be driven, and these are only on the south-western side of the island.
The only one of any consequence is that running from Noumea to
Bouloupari, a distance of about thirty miles. At Bourail, which is the great
agricultural settlement, there are about twelve miles of road and a long ago
abandoned railway bed. Between La Foa and Moindou there is another road
about as long; but both are isolated by miles of mountain and bush from each
other and are therefore of very little general use.
One has only to contrast them with the magnificent coach roads made in a
much shorter space of time through the far more difficult Blue Mountain
district in New South Wales to see the tremendous difference between the
British and the French ideas of colonisation, to say nothing of the railways—
two thousand seven hundred miles—and thirty-three thousand miles of
telegraph lines.
The result of this scarcity of roads and absolute absence of railways is that
when you want to go from anywhere to anywhere else in New Caledonia you
have to take the Service des Côtes, which for dirt, discomfort, slowness, and
total disregard of the convenience of passengers I can only compare to the
Amalgamated Crawlers presently known as the South-Eastern and Chatham
Railways. Like them, it is, of course, a monopoly, wherefore if you don’t like to
go by the boats you can either swim or walk.
The Island of “Le Sphinx,” one of the tying-up places on the south-west coast of New
Caledonia.

The whole of New Caledonia is surrounded by a double line of exceedingly


dangerous reefs, cut here and there by “passes,” one of which Captain Cook
failed to find, and so lost us one of the richest islands in the world. The
navigable water both inside and outside the reefs is plentifully dotted with tiny
coral islands and sunken reefs a yard or so below the surface and always
growing, hence navigation is only possible between sunrise and sunset. There
is only one lighthouse in all Caledonia.
Thus, when I began to make my arrangements for going to Bourail, I found
that I should have to be on the wharf at the unholy hour of 4.30 a.m. I
packed my scanty belongings overnight. At 4.15 the cab was at the door. The
cochers of Noumea either work in relays or never go to sleep. I was just
getting awake, and the gorged mosquitoes were still sleeping. I dressed and
drank my coffee to the accompaniment of considerable language which
greatly amused the copper-skinned damsel who brought the coffee up. She
also never seemed to sleep.
Somehow I got down to the wharf, and presented myself at the douannerie
with my “Certificat de Santé,” which I had got from the hospital the previous
evening. The doctor in charge gave me a look over, and countersigned it.
Then I went with my luggage into an outer chamber. My bag and camera-
cases were squirted with phenic acid from a machine which looked like a cross
between a garden hose and a bicycle foot-pump. Then I had to unbutton my
jacket, and go through the same process. The rest of the passengers did the
same, and then we started in a strongly smelling line for the steamer.
As we went on board we gave up our bills of health, after which we were
not permitted to land again under penalty of forfeiting the passage and being
disinfected again. Our luggage now bore yellow labels bearing the legend,
“colis désinfecté,” signed by the medical inspector. These were passed on to
the ships by Kanakas, who freely went and came, and passed things to and
from the ship without hindrance. As Kanakas are generally supposed to be
much better carriers of the plague than white people, our own examination
and squirting seemed a trifle superfluous.
The steamer was the St. Antoine, which may be described as the Campania
of the Service des Côtes. Until I made passages on one of her sister-ships—to
be hereafter anathematised—I didn’t know how bad a French colonial
passenger-boat could be. Afterwards I looked back to her with profound
regret and a certain amount of respect; wherefore I will not say all that I
thought of her during the eleven hours that she took to struggle over the
sixty-odd miles from Noumea to Bourail.
There is no landing-place at the port of Bourail, save for boats, so, after the
usual medical inspection was over and I had made myself known to the
doctor, I went ashore in his boat. The Commandant was waiting on the shore
with his carriage. I presented my credentials, and then came the usual
consommations, which, being literally interpreted, is French for mixed drinks,
after which we drove off to the town of Bourail, eight kilometres away. As we
were driving down the tree-arched road I noticed half a dozen horsewomen
seated astride à la Mexicaine, with gaily coloured skirts flowing behind.
“Ah,” I said, “do your ladies here ride South American fashion?”
“My dear sir,” he replied, “those are not ladies. They are daughters of
convicts, born here in Bourail, and reared under the care of our paternal
government! But that is all stopped now, later on you will see why.”
“Yes,” I said, “I have heard that you have given up trying to make good
colonists out of convict stock.”
“Yes,” he replied; “and none too soon, as you will see.”
From which remark I saw that I had to do with a sensible man, so I
straightway began to win his good graces by telling him stories of distant
lands, for he was more of a Fleming than a Frenchman, and was therefore
able to rise to the conception that there are other countries in the world
besides France.
I found Bourail a pretty little township, consisting of one street and a
square, in the midst of which stood the church, and by dinner-time I found
myself installed in a little hotel which was far cleaner and more comfortable
than anything I had seen in Noumea, except the club. When I said good-night
to the Commandant, he replied:
“Good-night, and sleep well. You needn’t trouble to lock your door. We are
all criminals here, but there is no crime.”
Which I subsequently found to be perfectly true.
Everything in New Caledonia begins between five and half-past, unless you
happen to be starting by a steamer, and then it’s earlier. My visit to Bourail
happened to coincide with a governmental inspection, and early coffee was
ordered for five o’clock. That meant that one had to get tubbed, shaved, and
dressed, and find one’s boots a little before five. Bar the Black Death, I
disliked New Caledonia mostly on account of its early hours. No civilised
persons, with the exception of milkmen and criminals under sentence of
death, ought to be obliged to get up before nine.
Still, there was only one bath in the place, and I wanted to be first at it, so
I left my blind up, and the sun awoke me.
I got out of bed and went on to the balcony, and well was I rewarded even
for getting up at such an unrighteous hour. The night before it had been
cloudy and misty, but now I discovered with my first glance from the
verandah that I had wandered into something very like a paradise.
I saw that Bourail stood on the slope of a range of hills, and looked out
over a fertile valley which was dominated by a much higher range to the
north-east. The sun wasn’t quite up, and neither were the officers of the
Commission, so I went for my bath. There were no mosquitos in Bourail just
then, and I had enjoyed for once the luxury of an undisturbed sleep. The
water, coming from the hills, was delightfully cool, and I came back feeling, as
they say between New York and San Francisco, real good.
The Commission, for some reason or other, did not get up before breakfast-
time (11.30), and so we got a good start of them. The Commandant had the
carriage round by six o’clock, and, after the usual consommations, we got
away. It was a lovely morning, the only one of the sort I saw in Bourail, for
the next day the clouds gathered and the heavens opened, and down came
the floods and made everything but wading and swimming impossible; but
this was a day of sheer delight and great interest.
We drove over the scene of a great experiment which, I fear, is destined to
fail badly. The province of Bourail is the most fertile in all Caledonia,
wherefore in the year 1869 it was chosen by the paternal French Government
as the Arcadia of the Redeemed Criminal. The Arcadia is undoubtedly there,
the existence of the redeemed criminal struck me as a little doubtful.
As soon as we got under way I reverted to the young ladies we had seen
on horseback the evening before.

A Native Temple, New Caledonia.


“You shall see the houses of their parents,” said the Commandant; “and
afterwards you will see the school where the younger ones are being
educated. For example,” he went on, pointing down the street we were just
crossing, “all those shops and little stores are kept by people who have been
convicts, and most of them are doing a thriving trade. Yonder,” he said,
waving his hand to the right, “is the convicts’ general store, the Syndicat de
Bourail. It was founded by a convict, the staff are convicts, and the customers
must be convicts. It is what you would call in English a Convict Co-operative
Store. It is managed by scoundrels of all kinds, assassins, thieves, forgers,
and others. I have to examine the books every three months, and there is
never a centime wrong. That is more than most of the great establishments in
Sydney could say, is it not?”
I made a non-committal reply, and said:
“Set a thief to catch a thief, or watch him.”
“Exactly! There is no other business concern in Caledonia which is managed
with such absolute honesty as this is. I should be sorry for the man who tried
to cheat the management.”
I knew enough of Caledonian society by this time to see that it would not
be good manners to press the question any further. Afterwards I had an
interview with the manager of the syndicate, an estimable and excellently
conducted forger, who had gained his rémission and was doing exceedingly
well for himself and his wife, who, I believe, had blinded somebody with
vitriol, and was suspected of dropping her child into the Seine.
He presented me with a prospectus of the company, which showed that it
had started with a government loan of a few hundred francs, and now had a
reserve fund of nearly forty thousand francs. He was a patient, quiet-spoken,
hard-working man who never let a centime go wrong, and increased his
personal profits by selling liquors at the back door.
Our route lay across the broad valley which is watered by the River Nera.
On either side the ground rose gently into little hillocks better described by
the French word collines and on each of these, usually surrounded by a grove
of young palms and a dozen acres or so of vineyards, orchards, manioc,
plantain, or maize, stood a low, broad-verandahed house, the residence of the
redeemed criminal.
I could well have imagined myself driving through a thriving little colony of
freemen in some pleasant tropical island upon which the curse of crime had
never descended, and I said so to the Commandant.
“Yes,” he said, “it looks so, doesn’t it? Now, you see that house up there to
the left, with the pretty garden in front. The man who owns that concession
was a hopeless scoundrel in France. He finished up by murdering his wife
after he had lived for years on the wages of her shame. Of course, the jury
found extenuating circumstances. He was transported for life, behaved
himself excellently, and in about seven years became a concessionnaire.
“He married a woman who had poisoned her husband. They have lived
quite happily together, and bring up their children most respectably.”
I was too busy thinking to reply, and he went on, pointing to the right:
“Then, again, up there to the right—that pretty house on the hill
surrounded by palms. The man who owns that was once a cashier at the Bank
of France. He was a ‘faussaire de première classe,’ and he swindled the bank
out of three millions of francs before they found him out. He was sent here for
twenty years. After eight he was given a concession and his wife and family
voluntarily came out to him. You see, nothing was possible for the wife and
children of a convict forger in Paris. Here they live happily on their little
estate. No one can throw stones at them, and when they die the estate will
belong to their children.”
“That certainly seems an improvement on our own system,” I said,
remembering the piteous stories I had heard of the wives and families of
English convicts, ruined through no fault of their own, and with nothing to
hope for save the return of a felon husband and father into a world where it
was almost impossible for him to live honestly.
“Yes,” he said; “I think so. Now, as we turn the corner you will see the
house of one of our most successful colonists. There,” he said, as the
wagonette swung round into a delightful little valley, “that house on the
hillside, with the white fence round it, and the other buildings to the side. The
owner of that place was a thief, a forger, and an assassin in Paris. He stole
some bonds, and forged the coupons. He gave some of the money to his
mistress, and found her giving it to some one else, so he stabbed her, and
was sent here for life.
“He got his concession, and married a woman who had been sent out for
infanticide, as most of them are here. If not that, it is generally poison. Well,
now he is a respectable colonist and a prosperous farmer. He has about forty
acres of ground well cultivated, as you see. He has thirty head of cattle and a
dozen horses, mares, and foals, to say nothing of his cocks and hens and
pigs. He supplies nearly the whole of the district with milk, butter, and eggs,
and makes a profit of several thousand francs a year. I wish they were all like
that!” he concluded, with a little sigh which meant a good deal.
“I wish we could do something like that with our hard cases,” I replied,
“instead of turning them out into the streets to commit more crimes and
beget more criminals. We know that crime is a contagious as well as an
hereditary disease, and we not only allow it to spread, but we even encourage
it as if we liked it.”
“It is a pity,” he said sympathetically, “for you have plenty of islands where
you might have colonies like this. You do not need to punish them. Remove
them, as you would remove a cancer or a tumour, and see that they do not
come back. That is all. Society would be better, and so would they.”
I could not but agree with this since every turn of the road brought us to
fresh proofs of the present success of the system, and then I asked again:
“But how do these people get their first start? One can’t begin farming like
this without capital.”
“Oh no,” he said, “the Government does that. For the first few years,
according to the industry and ability of the settler, these people cost us about
forty pounds a year each, about what you told me it costs you to keep a
criminal in prison. We give them materials for building their houses, tools, and
agricultural implements, six months’ provisions, and seed for their first
harvest. After that they are left to themselves.
“If they cannot make their farm pay within five years or so they lose
everything; the children are sent to the convent, and the husband and wife
must hire themselves out as servants either to other settlers or to free people.
If they do succeed the land becomes absolutely theirs in ten years. If they
have children they can leave it to them, or, if they prefer, they can sell it.
“Some, for instance, have got their rehabilitation, their pardon, and
restoration of civil rights. They have sold their farms and stock and gone back
to France to live comfortably. Their children are, of course, free, though the
parents may not leave the colony without rehabilitation. After breakfast I will
take you down the street of Bourail, and introduce you to some who have
done well in trade, and to-morrow or next day you can see what we do with
the children.”
VI
SOME HUMAN DOCUMENTS

Society in Bourail, although in one sense fairly homogeneous, is from


another point of view distinctly mixed. Here, for example, are a few personal
items which I picked up during our stroll down the main and one street of the
village.
First we turned into a little saddler’s shop, the owner of which once boasted
the privilege of making the harness for Victor Emmanuel’s horses.
Unfortunately his exuberant abilities were not content even with such
distinction as this, and so he deviated into coining, with the result of hard
labour for life. After a few years his good conduct gained him a remission of
his sentence, and in due course he became a concessionnaire. His wife, who
joined him after his release, is one of the aristocrats of this stratum of
Bourailian society.

Permit to visit a Prison or Penitentiary Camp en détail. This is the ordinary form; but the
Author is the only Englishman for whom the words in the left-hand corner were crossed out.
There is quite a little romance connected with this estimable family. When
Madame came out she brought her two daughters with her. Now the elder of
these had been engaged to a young man employed at the Ministry of
Colonies, and he entered the colonial service by accepting a clerkship at
Noumea. The result was naturally a meeting, and the fulfilment of the proverb
which says that an old coal is easily rekindled. The engagement broken off by
the conviction was renewed, and the wedding followed in due course. The
second daughter married a prosperous concessionnaire, and the ex-coiner,
well established, and making plenty of properly minted money, has the
satisfaction of seeing the second generation of his blood growing up in peace
and plenty about him. Imagine such a story as this being true of an English
coiner!
A little further on, on the left hand side, is a little lending library, and
cabinet de lecture. This is kept by a very grave and dignified-looking man,
clean-shaven, and keen-featured, and with the manners of a French
Chesterfield. “That man’s a lawyer,” I said to the Commandant, as we left the
library. “What is he doing here?”
“You are right. At least, he was a lawyer once, doing well, and married to a
very nice woman; but he chose to make himself a widower, and that’s why
he’s here. The old story, you know.”
Next door was a barber’s shop kept by a most gentle-handed housebreaker.
He calls himself a “capillary artist,” shaves the officials and gendarmerie, cuts
the hair of the concessionnaires, and sells perfumes and soaps to their wives
and daughters. He also is doing well.
A few doors away from him a liberé has an establishment which in a way
represents the art and literature of Bourail. He began with ten years for
forgery and embezzlement. Now he takes photographs and edits, and, I
believe, also writes the Bourail Indépendent. As a newspaper for ex-convicts
and their keepers, the title struck me as somewhat humorous.
Nearly all branches of trade were represented in that little street. But these
may be taken as fairly representative samples of the life-history of those who
run them. First, crime at home; then transportation and punishment; and then
the effort to redeem, made in perfect good faith by the Government, and, so
far as these particular camps and settlements are concerned, with distinct
success in the present.
Unhappily, however, the Government is finding out already that free and
bond colonists will not mix. They will not even live side by side, wherefore
either the whole system of concessions must be given up, or the idea of
colonising one of the richest islands in the world with French peasants,
artisans, and tradesmen must be abandoned.
Later on in the afternoon we visited the Convent, which is now simply a
girls’-school under the charge of the Sisters of St. Joseph de Cluny. A few
years ago this convent was perhaps the most extraordinary matrimonial
agency that ever existed on the face of the earth. In those days it was
officially styled, “House of Correction for Females.” The sisters had charge of
between seventy and eighty female convicts, to some of whom I shall be able
to introduce you later on in the Isle of Pines, and from among these the
bachelor or widower convict, who had obtained his provisional release and a
concession, was entitled to choose a bride to be his helpmeet on his new start
in life. The method of courtship was not exactly what we are accustomed to
consider as the fruition of love’s young or even middle-aged dream.

The Kiosk in which the Convict Courtships were conducted at Bourail.

After Mass on a particular Sunday the prospective bridegroom was


introduced to a selection of marriageable ladies, young and otherwise. Of
beauty there was not much, nor did it count for much. What the convict-
cultivator wanted, as a rule, was someone who could help him to till his fields,
look after live-stock, and get in his harvests.
When he had made his first selection the lady was asked if she was
agreeable to make his further acquaintance. As a rule, she consented,
because marriage meant release from durance vile. After that came the
queerest courtship imaginable.
About fifty feet away from the postern door at the side of the Convent there
still stands a little octagonal kiosk of open trellis-work, which is completely
overlooked by the window of the Mother Superior’s room. Here each Sunday
afternoon the pair met to get acquainted with each other and discuss
prospects.
Meanwhile the Mother Superior sat at her window, too far away to be able
to hear the soft nothings which might or might not pass between the lovers,
but near enough to see that both behaved themselves. Along a path, which
cuts the only approach to the kiosk, a surveillant marched, revolver on hip
and eye on the kiosk ready to respond to any warning signal from the Mother
Superior.
As a rule three Sundays sufficed to bring matters to a happy
consummation. The high contracting parties declared themselves satisfied
with each other, and the wedding day was fixed, not by themselves, but by
arrangement between those who had charge of them.
Sometimes as many as a dozen couples would be turned off together at the
mairie, and then in the little church at the top of the market-place touching
homilies would be delivered by the good old curé on the obvious subject of
repentance and reform. A sort of general wedding feast was arranged at the
expense of the paternal Government, and then the wedded assassins, forgers,
coiners, poisoners, and child-murderers went to the homes in which their new
life was to begin.
This is perhaps the most daring experiment in criminology that has ever
been made. The Administration claimed success for it on the ground that
none of the children of such marriages have ever been convicted of an
offence against the law. Nevertheless, the Government have most wisely put a
stop to this revolting parody on the most sacred of human institutions, and
now wife-murderers may no longer marry poisoners or infanticides with full
liberty to reproduce their species and have them educated by the State, to
afterwards take their place as free citizens of the colony.
The next day we drove out to the College of the Marist Brothers. It is really
a sort of agricultural school, in which from seventy to eighty sons of convict
parents are taught the rudiments of learning and religion and the elements of
agriculture.
During a conversation with the Brother Superior I stumbled upon a very
curious and entirely French contradiction. I had noticed that families in New
Caledonia were, as a rule, much larger than in France, and I asked if these
were all the boys belonging to the concessionnaires of Bourail.
“Oh no!” he replied; “but, then, you see, we have no power to compel their
attendance here. We can only persuade the parents to let them come.”
“But,” I said, “I understood that primary education was compulsory here as
it is in France.”
“For the children of free people, yes,” he replied regretfully, and with a very
soft touch of sarcasm, “but for these, no. The Administration has too much
regard for the sanctity of parental authority.”
When the boys were lined up before us in the playground I saw about
seventy-six separate and distinct reasons for the abolition of convict
marriages. On every face and form were stamped the unmistakable brands of
criminality, imbecility, moral crookedness, and general degeneration, not all on
each one, but there were none without some.
Later on I started them racing and wrestling, scrambling and tree-climbing
for pennies. They behaved just like monkeys with a dash of tiger in them, and
I came away more convinced than ever that crime is a hereditary disease
which can finally be cured only by the perpetual celibacy of the criminal. Yet
in Bourail it is held for a good thing and an example of official wisdom that
the children of convicts and of freemen shall sit side by side in the schools
and play together in the playgrounds.
Berezowski, the Polish Anarchist who attempted to murder
Napoleon III. and the Tsar Alexander II. in the Champs
Elysées. All Criminals in New Caledonia are photographed in
every possible hirsute disguise; and finally cropped and
clean shaven.

By permission of C. Arthur Pearson, Ltd.

On our way home I was introduced to one of the most picturesque and
interesting characters that I met in the colony. We pulled up at the top of a
hill. On the right hand stood a rude cabin of mud and wattles thatched with
palm-leaves, and out of this came to greet us a strange, half-savage figure,
long-haired, long-bearded, hairy almost as a monkey on arms and legs and
breast, but still with mild and intelligent features, and rather soft brown eyes,
in which I soon found the shifting light of insanity.
Acting on a hint the Commandant had already given me, I got out and
shook hands with this ragged, shaggy creature, who looked much more like a
man who had been marooned for years on a far-away Pacific Island, than an
inhabitant of this trim, orderly Penal Settlement. I introduced myself as a
messenger from the Queen of England, who had come out for the purpose of
presenting her compliments and inquiring after his health.
This was the Pole Berezowski, who more than thirty years ago fired a
couple of shots into the carriage in which Napoleon III. and Alexander II.
were driving up the Champs Elysées. He is perfectly harmless and well-
behaved; quite contented, too, living on his little patch and in a world of
dreams, believing that every foreigner who comes to Bourail is a messenger
from some of the crowned heads of Europe, who has crossed the world to
inquire after his welfare. Through me he sent a most courteous message to
the Queen, which I did not have the honour of delivering.
That night the storm-clouds came over the mountains in good earnest, and
I was forced to abandon my intention of returning to Noumea by road, since
the said road would in a few hours be for the most part a collection of
torrents, practically impassible, to say nothing of the possibility of a cyclone.
There was nothing more to be seen or done, so I accepted the Commandant’s
offer to drive me back to the port.
On the way he told me an interesting fact and an anecdote, both of which
throw considerable light upon the convict’s opinion of the settlement of
Bourail.
The fact was this: There are in New Caledonia a class of convicts who
would be hard to find anywhere else. These are voluntary convicts, and they
are all women. A woman commits a crime in France and suffers imprisonment
for it. On her release she finds herself, as in England, a social outcast, with no
means of gaining a decent living. Instead of continuing a career of crime, as is
usually the case here, some of these women will lay their case before the
Correctional Tribunal, and petition to be transported to New Caledonia, where
they will find themselves in a society which has no right to point the finger of
scorn at them.
As a rule the petition is granted, plus a free passage, unless the woman has
friends who can pay. Generally the experiment turns out a success. The
woman gets into service or a business, or perhaps marries a liberé or
concessionnaire, and so wins her way back not only to respectability as it
goes in Caledonia, but sometimes to comfort and the possession of property
which she can leave to her children.
As a matter of fact, the proprietress of the little hotel at the port was one of
these women. She had come out with a few hundred francs that her friends
had subscribed. She now owns the hotel, which does an excellent business, a
freehold estate of thirty or forty acres, and she employs fifteen Kanakas, half
a dozen convicts, and a Chinaman—who is her husband, and works harder
than any of them.
The anecdote hinged somewhat closely on the fact, and was itself a fact.
There is a weekly market at Bourail, to which the convict farmers bring their
produce and such cows, horses, calves, etc., as they have to sell. Every two or
three years their industry is stimulated and rewarded by the holding of an
agricultural exhibition, and, as a rule, the Governor goes over to distribute the
prizes. One of these exhibitions had been held, I regret to say, a short time
before my arrival, and the Governor who has the work of colonisation very
seriously at heart, made speeches both appropriate and affecting to the
various winners as they came to receive their prizes.
At length a hoary old scoundrel, who had developed into a most successful
stock-breeder, and had become quite a man of means, came up to receive his
prizes from his Excellency’s hands. M. Feuillet, as usual, made a very nice little
speech, congratulating him on the change in his fortunes, which, by the help
of a paternal government, had transformed him from a common thief and
vagabond to an honest and prosperous owner of property.
So well did his words go home that there were tears in the eyes of the
reformed reprobate when he had finished, but there were many lips in the
audience trying hard not to smile when he replied:
“Ah, oui, mon Gouverneur! if I had only known what good chances an
unfortunate man has here I would have been here ten years before.”
What his Excellency really thought on the subject is not recorded.
The hotel was crowded that night for the steamer was to sail for Noumea,
as usual, at five o’clock in the morning; but as Madame was busy she was
kind enough to give up her own chamber to me; and so I slept comfortably to
the accompaniment of a perfect bombardment of water on the corrugated
iron roof. Others spread themselves on tables and floors as best they could,
and paid for accommodation all the same.
By four o’clock one of those magical tropic changes had occurred, and
when I turned out the moon was dropping over the hills to the westward, and
Aurora was hanging like a huge white diamond in a cloudless eastern sky. The
air was sweetly fresh and cool. There were no mosquitos, and altogether it
was a good thing to be alive, for the time being at least.
Soon after the little convict camp at the port woke up. We had our early
coffee, with a dash of something to keep the cold out, and I made an early
breakfast on tinned beef and bread—convict rations—and both very good for
a hungry man. Then came the news that the steamboat La France had tied up
at another port to the northward on account of the storm, and would not put
in an appearance until night, which made a day and another night to wait, as
the coast navigation is only possible in daylight.
I naturally said things about getting up at four o’clock for nothing more
than a day’s compulsory loafing, but I got through the day somehow with the
aid of some fishing and yarning with the surveillants and the convicts, one of
whom, a very intelligent Arab, told me, with quiet pride, the story of his
escape from New Caledonia twelve years before.
He had got to Australia in an open boat, with a pair of oars, the branch of a
tree for a mast and a shirt for a sail. He made his way to Europe, roamed the
Mediterranean as a sailor for nine years, and then, at Marseilles, he had made
friends with a man who turned out to be a mouchard. This animal, after
worming his secret out of him under pledge of eternal friendship, earned
promotion by giving him away, and so here he was for life.
He seemed perfectly content, but when I asked him what he would do with
that friend if he had him in the bush for a few minutes, I was answered by a
gleam of white teeth, a flash of black eyes, and a shake of the head, which,
taken together, were a good deal more eloquent than words.
One of the Lowest Types of Criminal Faces. An illustration of
the ease with which it is possible to disguise the chin, typical
of moral weakness, and the wild-beast mouth, which nearly
all Criminals have, by means of moustache and beard.

By permission of C. Arthur Pearson, Ltd.

La France turned up that afternoon, so did the Commission of Inspection


from Bourail with several other passengers. I was told that we should be
crowded, but until I got on board in the dawn of the next morning I never
knew how crowded a steamer could be.
I had travelled by many crafts under sail and steam from a south sea island
canoe to an Atlantic greyhound, but never had the Fates shipped me on board
such a craft as La France. She was an English-built cargo boat, about a
hundred and thirty feet long, with engines which had developed sixty horse-
power over twenty years ago. She had three cabins on each side of the dog-
kennel that was called the saloon.
If she had been allowed to leave an English port at all she would have been
licensed to carry about eight passengers aft and twenty on deck. On this
passage she had twelve first-class, about fifteen second, and between fifty
and sixty on deck, including twenty convicts and relégués on the forecastle,
and a dozen hard cases in chains on the forehatch.
She also carried a menagerie of pigs, goats, sheep, poultry, geese, and
ducks, which wandered at their own will over the deck-cargo which was piled
up to the tops of her bulwarks. Her quarter-deck contained about twenty
square feet, mostly encumbered by luggage. The second-class passengers
had to dine here somehow. The first-class dined in the saloon in relays.
The food was just what a Frenchman would eat on a Caledonian coast-boat.
It was cooked under indescribable conditions which you couldn’t help seeing;
but for all that the miserable meals were studiously divided into courses just
as they might have been in the best restaurant in Paris.
Everything was dirty and everything smelt. In fact the whole ship stank so
from stem to stern that even the keenest nose could not have distinguished
between the smell of fried fish and toasted cheese. The pervading odours
were too strong. Moreover, nearly every passenger was sick in the most
reckless and inconsiderate fashion; so when it came to the midday meal I got
the maître d’hôtel, as they called the greasy youth who acted as chief
steward, to give me a bottle of wine, a little tin of tongue, and some fairly
clean biscuits, and with these I went for’rard on to the forecastle and dined
among the convicts.
The forecastle was high out of the water, and got all the breeze, and the
convicts were clean because they had to be. I shared my meal and bread and
wine with two or three of them. Then we had a smoke and a yarn, after which
I lay down among them and went to sleep, and so La France and her unhappy
company struggled and perspired through the long, hot day back into plague-
stricken Noumea. When I left La France I cursed her from stem to stern, and
truck to kelson. If language could have sunk a ship she would have gone
down there and then at her moorings; but my anathemas came back upon my
own head, for the untoward Fates afterwards doomed me to make three more
passages in her.
To get clean and eat a decent dinner at the Cercle was something of a
recompense even for an all-day passage in La France. But it is not a very
cheerful place to come back to, for the shadow of the Black Death was
growing deeper and deeper over the town. The plague was worse than ever.
The microbe had eluded the sentries and got under or over the iron barriers,
and was striking down whites and blacks indiscriminately, wherefore I
concluded that Noumea was a very good place to get out of, and, as I
thought, made my arrangements for doing so as quickly as possible.

VII
THE PLACE OF EXILES

My next expedition was to include the forest camps to the south-west of the
island, and a visit to the Isle of Pines, an ocean paradise of which I had read
much in the days of my youth; wherefore I looked forward with some
anticipation to seeing it with the eyes of flesh. There would be no steamer for
three or four days, so the next day I took a trip over to the Peninsula of
Ducos, to the northward of the bay.
The glory of Ducos as a penal settlement is past. There are now only a few
“politicals,” and traitors, and convicts condemned a perpétuité; that is to say,
prisoners for life, with no hope of remission or release. A considerable
proportion of them are in hospital, dragging out the remainder of their
hopeless days, waiting until this or the other disease gives them final release.
The Peninsula of Ducos. In the background is Ile Nou with the Central Criminal Depôt.

On another part of the peninsula, in a semi-circular valley, hemmed in by


precipitous hills, there is a piteously forlorn colony, that of the liberés
collectifs; that is to say, convicts who have been released from prison, but are
compelled to live in one place under supervision. They are mostly men whose
health has broken down under the work of the bagne, or who have been
released on account of old age.
They live in wretched little cabins on the allotments, which it is their
business to keep in some sort of cultivation. They have the poor privileges of
growing beards and moustaches if they like, and of wearing blue dungaree
instead of grey, and of earning a few pence a week by selling their produce to
the Administration.
This is not much, but they are extremely proud of it, and hold themselves
much higher than the common forçat. They do not consider themselves
prisoners, but only “in the service of the Administration.” I have seldom, if
ever, seen a more forlorn and hopeless collection of human beings in all my
wanderings.
There was, however, a time when Ducos was one of the busiest and most
important of the New Caledonian Settlements, for it was here that the most
notorious and most dangerous of the communards were imprisoned after their
suppression in 1872. Here lived Louise Michel, the high-priestess of anarchy,
devoting herself to the care of the sick and the sorrowing with a self-sacrifice
which rivalled even that of the Sisters of Mercy, and here, too, Henri Rochefort
lived in a tiny stone house in the midst of what was once a garden, and the
delight of his days of exile.
Louise Michel’s house has disappeared in the course of improvements.
Rochefort’s house is a roofless ruin in the midst of a jungle which takes a
good deal of getting through. It was from here that he made his escape with
Pain and Humbert and two other communards in an English cutter, which may
or may not have been in the harbour for that particular purpose.
One night they did not turn up to muster, but it was explained that
Rochefort and Humbert had gone fishing, and the others were away on a tour
“with permission.” As they did not return during the night search-parties were
sent out for them. Meanwhile, they had kept a rendezvous at midnight with
the cutter’s boat and got aboard.
The next day was a dead calm; and, as the cutter lay helpless at her
anchor, the fugitives concealed themselves about her cargo as best they
could. The hue and cry was out all over the coast, but the searchers looked
everywhere but just the one place where they were. If the next day had been
calm they must have been caught, for the authorities had decided on a
thorough search of every vessel in the harbour. Happily for them a breeze
sprang up towards the next morning, and the cutter slipped quietly out. Once
beyond the outward reef the fugitives were in neutral water, and, being
political prisoners, they could not be brought back.
By daylight the truth was discovered, but pursuit was impossible. The cutter
had got too long a start for any sailing vessel to overtake her in the light
wind, and the only steamer which the administration then possessed had
gone away to Bourail to fetch back the Governor’s wife. If it had been in the
harbour that morning, at least one picturesque career might have been very
different. MacMahon was President at the time, and of all men on earth he
had the most deadly fear of Rochefort, so he took a blind revenge for his
escape by ordering the Governor to expel every one who was even suspected
of assisting in the escape.
The story was told to me by one who suffered through this edict quite
innocently, and to his utter ruin. He was then one of the most prosperous
men in Noumea. He owned an hotel and several stores, and had mail and
road-making contracts with the government. Unhappily, one of his stores was
on the Peninsula of Ducos, and the man who managed it was reputed to be
very friendly with Rochefort.
This was enough. He was ordered to clear out to Australia in two months. It
was in vain that he offered himself for trial on the definite charge of assisting
a prisoner to escape. The Governor and every one else sympathised deeply
with him, but they dare not even be just, and out he had to go. He is now
canteen-keeper on the Isle of Pines, selling groceries and drink to the officials
and relégués at prices fixed by the government. He told me this story one
night at dinner at his own table.
The general amnesty of 1880 released Louise Michel and the rest of those
who had survived the terrible revolt of 1871 from Ducos and the Isle of Pines.
There are, however, two other celebrities left on Ducos. One of them is a
tall, erect, grizzled Arab, every inch a chieftain, even in his prison garb. This is
Abu-Mezrag-Mokrani, one of the leaders of the Kabyle insurrection of 1871, a
man who once had fifteen thousand desert horsemen at his beck and call.
Now he rules a little encampment in one of the valleys of the peninsula,
containing forty or fifty of his old companions-in-arms, deported with him
after the insurrection was put down.
When the Kanaka rebellion broke out in New Caledonia in 1878, Abu-
Mezrag volunteered to lead his men against the rebels in the service of
France. The offer was accepted and the old warriors of the desert acquitted
themselves excellently among the tree-clad mountains of “La Nouvelle.” When
the rebellion was over a petition for their pardon was sent to the home
government, but the remnant of them are still cultivating their little patches of
ground on Ducos.
The other surviving celebrity is known in Caledonia as the Caledonian
Dreyfus, and this is his story:
In 1888 Louis Chatelain was a sous-officier of the line stationed in Paris. He
was dapper, good-looking, and a delightful talker. He engaged the affections
of a lady whose ideas as to expenditure were far too expansive to be gratified
out of the pay of a sous-officier. Poor Chatelain got into debt, mortgaged or
sold everything that he had, and still the lady was unsatisfied. Finally, after
certain recriminations, and when he had given her everything but his honour,
she suggested a means by which he could make a fortune with very little
trouble. She had, it appears, made the acquaintance of a gentleman who
knew some one connected with a foreign army, who would give twenty
thousand francs for one of the then new-pattern Lebel rifles.
He entered into correspondence with the foreign gentleman, addressing
him—c/o the —— Embassy, Paris. His letters were stopped, opened,
photographed, and sent on. So were the replies. Then the negotiations were
suddenly broken off, Chatelain was summoned before the military tribunal and
confronted with the pièces de conviction. He confessed openly, posing as a
martyr to la grande passion—and his sentence was deportation for life.

The remains of Henri Rochefort’s House.

The Bedroom of Louis Chatelain, “The Caledonian


Dreyfus” in Ducos. The photographs on the wall and the
one on the table are those of the woman who ruined
him.
When I went into his little sleeping-room at Ducos, I found on a little table
beside his mosquito-curtained bed, a photograph of a very good-looking
young woman. On the wall above the table there were two others of the same
enchantress, the evil genius of his life. The moment he fell she deserted him.
Unlike many another Frenchwoman, who has done so for lover or husband,
she did not follow him across the world to Caledonia, and yet every night and
morning of his life Louis Chatelain kneels down in front of that table as he
might before an altar, and says his prayers with his eyes on those
photographs.

VIII
A PARADISE OF KNAVES

For the next three or four days after my visit to the Peninsula of Ducos
there was nothing definite to be learnt about means of transit. In fact there
was nothing certain except the plague—always that Spectre which seemed to
stand at the end of every pathway. It was really getting quite monotonous,
and I was beginning to wonder whether I should ever get out of Noumea at
all.
Then I began making inquiries as to an over-land journey through the
interior. No, that was impossible, save at great risk and expense. The Spectre
had jumped the mountains. Huge armies of rats had appeared in the bush,
just as though some Pied Piper of Hamelin had enticed them away from the
towns into the mountains, and they were spreading the plague in all
directions among the Kanakas.
It is a curious fact that rats, who of all animals are the most susceptible to
the plague, will migrate from a plague-stricken town just as they will try to
escape from a sinking ship.
Convicts and Kanakas were dying in unknown numbers. Camps were being
closed, and the rains were coming on. There was nothing to be seen or done
worth seeing or doing, so I had to content myself with wandering about
Noumea and the neighbourhood, taking photographs, making acquaintances
with convicts and liberés and getting stories out of them, wondering the
while, as every one else was doing, what the Spectre was going to do next.
As far as I was concerned, he did me the unkindest turn that he could have
done, save one. He infected the only two decent boats on the Coast Service,
and so left me the choice between voyaging to the Isle of Pines in La France
or stopping where I was.
I had to get to the island somehow, so I chose La France, and at five
o’clock one morning, after being duly inspected and squirted, I once more
boarded the detestable little hooker.
I thought my first passage in her was bad enough, but it was nothing to
this. She was swarming with passengers, bond and free, black, white, and
yellow, from end to end. She was loaded literally down to the deck, and she
smelt, if possible, even stronger than she did before. The worst of this was
that before we got to the Isle of Pines we had to get outside the reef and into
the open water.
I have seen too much of seafaring to be easily frightened on salt water, but
I candidly admit that I was frightened then. In fact, when we got outside and
she began to feel the swell, I took out my swimming-jacket and put it on,
though, of course this was a pretty forlorn hope, as the water was swarming
with sharks and the shortest swim would have been a couple of miles. Still,
one always likes to take the last chance.
Happily, she was English-built, and high in the bows, so she took nothing
but spray over. Two or three green seas would have swamped her to a
certainty, but they didn’t come, and so in time we got there.
On board I renewed the acquaintance of the Commandant of Ile Nou, who
was taking his wife and family to the Isle of Pines, which is to Caledonia as
the Riviera is to Europe. At midday we stopped at Prony, the headquarters of
the forest camps which I was to visit later on my return; and we lunched in
the saloon with six inches of water on the floor. That was the first time I ever
saw a steamer baled out with buckets. Still, they managed to get the water
under somehow. There didn’t appear to be a pump on board.
When we passed the reef, and started on the sixty-mile run through the
open sea, some began to say their prayers and some said other things, but in
the end we worried through, and just as the evening star was growing golden
in the west we anchored in the lovely little Bay of Kuto.
Never before had I heard the anchor chain rumble through the hawse-hole
with greater thankfulness than I did then, and, judging by the limp and
bedraggled look of every one, bond and free, who went ashore, I don’t think I
was alone in hoping that I had seen the last of La France—which I hadn’t.
My friend the Commandant introduced me to his confrère of the Isle of
Pines. He was not particularly sympathetic. I believe I was the only
Englishman who had ever come to the island with authority to inspect his
domains, and he didn’t take very kindly to the idea. Still, ruler and all as he
was in his own land, the long arm of the Minister of Colonies reached even to
the Isle of Pines, and, although he did not even offer me the usual courtesy of
a glass of wine, he handed the credentials back to me, and said:
“Très bien, monsieur! If you will come and see me at nine o’clock to-
morrow morning we will make arrangements. You will, I think, find
accommodation at the canteen.”
With that I took my leave, and went out into the darkness to find the
canteen and some one to carry my luggage there. I found a surveillant, who
found a relégué, and he shouldered my bag and found the canteen, the only
semblance of an hotel on the island.
There, quite unknowingly, I stumbled upon excellent friends. The canteen-
keeper was the man whose story I told in the last chapter. I was a stranger
from a very strange land. Their resources are very limited; for
communications with the grand terre were few and far between, and yet the
twenty days that I was compelled to stop on the Isle of Pines, proved after all
to be the pleasantest time that I had spent in New Caledonia.
But there was one exception, happily only a transient experience, yet bad
enough in its way. If the plague was not on board La France it ought to have
been, for never did a fitter nursery of microbes get afloat, and when I got into
the wretched little bedroom, which was all they could fix up for me that night,
I honestly believed that the little wriggling devil had got into the white
corpuscles of my blood.
I had all the symptoms with which the conversation of the doctors at the
Cercle in Noumea had made me only too familiar—headache, stomachache,
nausea, dizziness, aching under the armpits and in the groins.
Of course, I was about as frightened as an ordinary person could very well
be, a great deal more so in fact than I had been a few years before when I
first experienced the sensation of being shot at. It may have been the fright
or the fact, but the glands were swelling.
Then I caught myself repeating fragments of “Abide with me,” mixed up
with Kipling’s “Song of the Banjo”; and when a lucid interval came I decided
that the case was serious.

You might also like