Building an Engel Application

This section will cover the creation of a basic Engel application that will display the headlines from Reddit using PRAW.

Let’s begin by installing PRAW.

$ pip install praw

Generating the project files

Once PRAW is installed, let’s use Engel’s built-in code generator to generate the basic skeleton of our application.

$ eng new engelreddit

This will generate the following structure:

engelreddit/                  - main app directory
├── app.py                    - application entry point
├── views/                    - views package
│   ├── home.py               - Default home view
├── services/                 - services package
│   ├── home.py               - default home service

Building the service

Let’s rename services/home.py to services/reddit.py and edit it so that the contents look like:

import praw


class RedditService(object):

  def __init__(self):
    self.agent = praw.Reddit(user_agent='engelreddit')

  def get_sub(self, subreddit):
    return [str(x) for x in self.agent.get_subreddit(subreddit).get_hot(limit=50)]

The service provides only one method, which fetches the top 50 submissions from a given subreddit. This is the only logic needed in our application.

Next, let’s edit app.py so it is up-to-date with our service.

from engel import Application

from views.home import HomeView
from services.reddit import RedditService


class engelreddit(Application):

  base_title = "{0} | engelreddit"

  def __init__(self, debug=False):
    super(engelreddit, self).__init__(debug)

    self.views['default'] = HomeView

    self.services['reddit'] = RedditService

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

When the app starts, the framework instantiates all services defined in Application.services and first builds the view corresponding to the default route. Now we only need a view for our application to work.

Building the view

The bulk of the view definition process is done in the build() method, which must be overidden in all of your views. This method is called by the framework when loading a view, and is tasked with building the layout for the view as well as registering most of the events that are to be handled at runtime.

With that in mind, let’s define our layout in /views/home.py.

Note

When using an external library (such as bootstrap4), you must add the module to YourView.libraries, so that the view loader is able to load the CSS and Javascript files required by your library.

from engel import View

from engel.libraries import bootstrap4
from engel.widgets import TextBox, Button

from copy import copy


class HomeView(View):

  title = "HomeView"

  libraries = [bootstrap4]

  def build(self):
    self.main_panel = bootstrap4.Container(id="main-panel", parent=self.root)

    self.results = bootstrap4.CardColumns(id="results", parent=self.main_panel)

    self.txt_subreddit = TextBox(id="txt-subreddit", name="subreddit", parent=self.main_panel)
    btnSearch = Button(id="btn-get-sub", text="Get Subreddit", parent=self.main_panel)

    self.on(event='click', callback=self.load_subreddit, selector='#' + btnSearch.id)

  def clear_results(self):
    for rs in copy(self.results.children):
      self.results.remove_child(rs)

  def load_subreddit(self, event, interface):
    self.clear_results()
    subreddit = self.txt_subreddit.text

    if subreddit:
      for i, hit in enumerate(self.context.services['reddit'].get_sub(subreddit)):
        print(hit)
        bootstrap4.ImageCard(
          id="result-" + str(i),
          title=hit,
          text=str(i),
          img_url="http://i.imgur.com/CduSn7x.png",
          parent=self.results
        )

You now have a fully functional Engel application! If you want more information on the framework’s API, head over to the User API Overview. Otherwise, take a look at Extending Engel With Widgets.