Moon Flask is a simple portfolio web app built on Flask.
The app comes with 'about' and 'contact' pages, and generates additional pages and their navigation links from a database. Moon Flask uses SQLAlchemy for database management, Skeleton CSS for page layout and Font-Awesome for social icons.
The app comes with a sample set of content, styles and a sample user, the Early Renaissance painter Paolo Uccello.
Make a folder for Moon Flask, then clone the repository into it: ``` $ git clone Clone the Repositoryhttps://github.com/thuselem/moon-flask ```
Moon Flask was developed in Python 3.4. I recommend Python 3.4, but the app will also work in Python 2.7. Install Python
On Mac OS X and Windows, you may need to install Python 3.4. Ubuntu Linux 14.04 and later come with Python 3.4 installed.
Check if Python 3.4 is installed. On Mac OS X or Linux:
On Windows, enter the full path of the Python 3.4 executable. This should be:
If Python 3.4 is installed, an interactive shell will open and report Python 3.4. (
exit() returns you to your command prompt.)
A virtual environment is a sandbox for a Python application. Any extensions and packages you install to it are isolated, preventing conflicts with your system environment and other virtual environments. Install Virtualenv
We will use
virtualenv to create our virtual environment. You can also create your virtual environment using
venv if you prefer.
virtualenv on Mac OS X:
$ sudo easy_install virtualenv
$ pip install virtualenv
Use your package manager on Linux distributions. For example, on Ubuntu:
$ sudo apt-get install python-virtualenv
If Python 3.4 is your only Python installation: ``` $ virtualenv moon-flask ``` If you have more than one version of Python on your system, specify Python 3.4: ``` $ virtualenv -p python3.4 moon-flask ``` On Windows, specify the full path of the executable. With the default Python installation, this will be: ``` $ virtualenv -p C:\Python34\python.exe moon-flask ``` Set up the Virtual Environment
Next we will install the required packages in the virtual environment. First, activate the virtual environment: ``` $ cd moon-flask $ source bin/activate ``` On Windows: ``` $ cd moon-flask $ Scripts\activate ``` Your command line prompt will now start with (moon-flask), indicating the virtual environment is active. Now install the required packages using pip: ``` $ pip install -r requirements.txt ``` Install Flask, SQLAlchemy and Flask Extensions
The `build_db.py` script will build a database for our sample user Paolo Uccello: ``` $ python build_db.py ``` Build the Sample Database
Environment variables must be set for `SECRET_KEY`, `MAIL_USERNAME` and `MAIL_PASSWORD`. These variables can be temporarily set at the command line. Set the Environment Variables
SECRET_KEY to prevent cross-site request forgery. A hard-coded default is included for
SECRET_KEY, but please make up your own key and store it as an environment variable for effective CSRF protection. To set the
SECRET_KEY on Mac OS X or Linux:
$ export SECRET_KEY='Crazy,long_string'
$ set SECRET_KEY=Crazy,long_string
MAIL_PASSWORD environment variables are used by the flask-mail extension. When a user submits the form on the contact page, Moon Flask sends an outgoing mail request to an email server. The message is sent from and delivered to the email address specified in
MAIL_PASSWORD authenticates the send request.
To set these on Mac OS X or Linux:
$ export MAIL_USERNAMEfirstname.lastname@example.org' $ export MAIL_PASSWORD='email_password'
$ set MAIL_USERNAMEemail@example.com $ set MAIL_PASSWORD=email_password
The email server name, port, SSL and TLS are specified in
config.py. The defaults are set for a Yahoo account for testing purposes. Change these defaults to use your preferred email provider. (A warning, gmail will not work.)
Run Moon Flask Locally
Make sure your virtual environment is still active, then start the local development server: ``` $ python run.py runserver ``` Start the Development Server
Debug mode provides you with an interactive debugger in the browser. Do not use in production. ``` $ python run.py runserver -d ``` Debug Mode
When you have finished working with Moon Flask, deactivate the virtual environment: ``` $ deactivate ``` Deactivate the virtual environment
`ERD.png` details the database model. A User can have many Pages and Posts. Each Page can have many Posts. A User can have many Social Icons. Although the database model is constructed with multiple users in mind, at this point the app will only work for one user. Data Models and How They are Rendered
Each Page has a 'name' and a 'description'. Both are displayed in the header, 'name' as the page heading and 'description' as a subheading. The 'image' field is a boolean value. If
True, the 'page' template will display a properly named image above the page heading. See the section below on naming images.
Each Post has a 'title' and a 'body'. The 'title' and 'body' are displayed as post headings and bodies respectively. As with Pages, 'image' is a boolean test for an image associated with the Post. Each Post can render an 'image' or an 'embed'. Not both. The 'embed' is an iframe tag, including all HTML elements.
All Post fields are optional. This allows for modular construction of a Post. For example, longer posts could be built from multiple posts stitched together leaving out the 'title' field where appropriate. Posts could be just a 'title' and 'image'. To skip a field, assign it an empty string or set 'image' to
The Social Icons are displayed at the bottom of the contact page and each dynamically generated page. The fields for social icons are the 'href' link to the social media profile and the Font-Awesome 'css_value' of the desired icon. The Font-Awesome cheatsheet lists all possible icons and their css values. See the Font-Awesome documentation for details on resizing and manipulating icons.
Images must be placed in the `app/static/img/` folder. They must be .jpg files. Their name must match the 'name' field of their corresponding 'Page' or 'title' field for 'Post' images. Remove spaces and keep the capitalization scheme intact. For example, a Post with the title "The Bridges of Portland" would have a corresponding image named "TheBridgesofPortland.jpg". Naming Images
Moon-Flask does not have an Admin panel for managing content at this point. It will be better when it does. For now, the content must be managed manually. Manage Content
Use the commands in
build_db.py as a model for items you wish to add. Lines can be replaced in this script, but make sure to include your additions in the
db.session.add_all() before the commit statement.
Items can also be added, deleted or modified in the shell by running:
$ python run.py shell
The primary key 'id' field is automatically generated and need not be assigned.
The app uses SQLAlchemy and SQLite by default. Change
config.py to use another database. The script
build_db.py builds the SQLite database file
The best way to update the database file is to delete
data.sqlite and build the database from scratch. Note that SQLite cannot overwrite existing database entries. If you want to to add entries without deleting
data.sqlite, you must remove any existing database entries from
This app can be improved. Here are my top improvements: To do
1. Flexible image names and types
2. Better error handling in contact.py
3. Chronological display of posts
4. Async email
5. Admin panel for managing content
6. Support for multiple users
Being a neophyte Flask developer, I welcome any suggestions and best practice recommendations. Thank you!