This tutorial will demonstrate how fast you can prototype apps with Enferno Framework.

Final Comic App

Installation

Start by installing the framework, just make sure you have Python, Mongodb, and Redis installed, then you can follow the steps in this previous tutorial to install the framework.

Create your Admin User

Enferno ships with an management command that will setup a basic admin user/role for you, just execute the following command:

./manage.py install

and follow the instructions to create your first admin user.

Designing our Data Structure

Start by creating a file named “models.py” inside the “public” directory.

Create the “Comic” class:

from extensions import db



class Comic(db.Document):

image = db.ImageField()

title = db.StringField()



def __unicode__(self):

return '%s' % self.title

for the sake of simplicity, we will create two fields only: comic title, and Comig Image.

Generating the backend

Open the file “views.py” within the “admin” dir and add the following lines:

from public.models import Comic class ComicView(ModelView):

pass

Next, we let’s register our “ComicView” class with our main app so that we can activate the CRUD functionality. add this code to “app.py” file:

from public.models import Comic

from admin.views import ComicView

then add the following line within the “register_admin_views” method:

admin.add_view(ComicView(Comic))

Run the server using:

./manage.py server

Then visit the admin URL at:

and click on the Comic link, you should see the following

Add a few comics, we will need this data next when we create the font-end of our website.

Creating the front-end

We would like our app to display the latest comic on the front page, with next/back buttons to display other comics.

Let’s first modify our front page to display the latest Comic post.

open the “views.py” file within the “public” directory, change the front page route to the following:

from models import Comic @bp_public.route('/',defaults={'comic':None})

@bp_public.route('/<comic>')

def index(comic):

if comic is None:

comic=Comic.objects.order_by('-id').limit(1).first()

next_comic = None

prev_comic = Comic.objects.filter(id__lt=comic.id).order_by('-id').limit(1).first()

else:

try:

comic = Comic.objects.get(id=comic)

next_comic = Comic.objects.filter(id__gt=comic.id).order_by('-id').limit(1).first()

prev_comic = Comic.objects.filter(id__lt=comic.id).order_by('-id').limit(1).first()

except Exception, e:

abort(404)

return render_template('index.html',comic=comic, next_comic=next_comic, prev_comic=prev_comic)

In short, the front page will list the most recent comic by default (if no URL params are passed), Also it will render a specific comic if we pass the comic id in the URL.

the “prev_comic” and “next_comic” are two simple queries we need to pass to the template (for the next/previous buttons)

Since Mongo Engine stores images in Gridfs by default, we will need a way to get them and serve them, let’s add another route to our “views.py” file to serve images:

@bp_public.route('/img/<id>')

def img(id):

comic = Comic.objects(id=id).first()

mime_type = comic.image.content_type

return Response(comic.image.read(),mimetype=mime_type,direct_passthrough=True)

Then let’s update our templates, first open the “layout.html” and remove the “header” and “nav” elements as we won’t need them:

Delete the selected part in layout.html

Then replace the index.html with the following code:

{% extends 'layout.html' %}

{% block header %}

<ul class="navigation">

<li><a href="/{{ prev_comic.id|string }}">Previous Comic</a></li>

<li><a href="/{{ next_comic.id|string }}">Next Comic</a></li>

</ul>

{% endblock %}



{% block content %}

<main class="cd-main-content">

<div class="cd-container">

<img src="/img/{{ comic.id }}" alt=""/>

<p>{{ comic.title }}</p>



</div>

</main>

{% endblock %}

To style this further, open the “style.css” file located in “static/css” directory, add the following styles at the end of the file:

.cd-container {

max-width: 1100px;

text-align: center;

}

ul.navigation {

width: 500px;

margin: 0 auto;

padding: 40px 0;

text-align: center;

}

ul.navigation li {

display: inline-block;

margin: 0 20px;

text-transform: uppercase;

}

ul.navigation li a {

color: #222;

font-size: 24px;



}

Next, visit the page at http://127.0.0.1:5000/ , you should see something like the following:

Congrats ! you have created a simple comic app within a few minutes using Porject Enferno.

You can download the source code from Github