## 3. Pyramid:

A hybrid framework that brings the best of both worlds, be it big or small. Pyramid seeks to bridge the gap between Django and Flask. It was developed as a part of the Pylons Project, released in 2008, it draws inspiration from Django or smaller frameworks.

Mozilla and Yelp are among the companies that are reliant on the Pyramid for API development. The current version of Pyramid 1.10 is available for general use as it also documents the backwards incompatibilities between the two versions and deprecations added to Pyramid 1.10, as well as software dependency changes and notable documentation additions that aids api developers to foresee changes in API development.

STEP 1: Project setup
mkdir tutorial
CD tutorial
python3 -m venv env
source env/bin/activate
pip install pyramid cookiecutter SQLAlchemy

STEP 2: Creating project structure

cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.10-branch
If it is prompted for the first item, accept the default yes by hitting return.

You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
Is it okay to delete and re-clone it? [yes]: yes
project_name [Pyramid Scaffold]: myproject
repo_name [myproject]: myproject
Select template_language:
1 - jinja2
2 - chameleon
3 - mako
Choose from 1, 2, 3 [1]: 1
Select backend:
1 - none
2 - sqlalchemy
3 - zodb


________________



Choose from 1, 2, 3 [1]: 2


________________



STEP 3: Installing your Newly Created Project for Development


pip install -e ${PATH_TO_PROJECT}

STEP 4: Creating Models

touch {PROJECT_NAME}/models/user.py


In models/user.py




import datetime #<- will be used to set default dates on models
from pyramid_blogr.models.meta import Base  #<- we need to import our sqlalchemy metadata from which model classes will inherit
from sqlalchemy import (
   Column,
   Integer,
   Unicode,     #<- will provide Unicode field
   UnicodeText, #<- will provide Unicode text field
   DateTime,    #<- time abstraction field
)
class User(Base):
   __tablename__ = 'users'
   id = Column(Integer, primary_key=True)
   name = Column(Unicode(255), unique=True, nullable=False)
   password = Column(Unicode(255), nullable=False)
   last_logged = Column(DateTime, default=datetime.datetime.utcnow)



rm {PROJECT_NAME}/models/mymodel.py
Now it’s time to update our models/__init__.py to include our models. This is especially handy because it ensures that SQLAlchemy mappers will pick up all of our model classes and functions, like create_all, and that the models will do what you expect.
Add these imports to the file (remember to also remove the MyModel import).


# import or define all models here to ensure they are attached to the
# Base.metadata prior to any initialization routines
from .user import User



Update database initialization script
It’s time to update our database initialization script to mirror the changes in our models package.
We want to replace the following bits:
def setup_models(dbsession):
   """
  Add or update models / fixtures in the database.


   """
   model = models.mymodel.MyModel(name='one', value=1)
   dbsession.add(model)
with this:





def setup_models(dbsession):
   """
   Add or update models / fixtures in the database.


   """


   model = models.user.User(name=u'admin', password=u'admin')
   dbsession.add(model)



STEP 5 Creating templates and Views

Template


Create template/home.jinja2 file and following code to it.
{% extends "layout.jinja2" %}
{% block content %}
<h1>{{user.name}}</h1>
{% endblock content %}

Views

Create views/home.py file and following code to it.
from pyramid.view import view_config
from pyramid.response import Response


from sqlalchemy.exc import DBAPIError



from .. import models


@view_config(route_name='home', renderer='../templates/home.jinja2')
def my_view(request):
   try:
       query = request.dbsession.query(models.User)
       one = query.filter(models.User.name == 'admin').first()
   except DBAPIError:
       return Response(db_err_msg, content_type='text/plain', status=500)
   return {'user': one}




db_err_msg = """\
Pyramid is having a problem using your SQL database.  The problem
might be caused by one of the following things:


1.  You may need to initialize your database tables with `alembic`.
   Check your README.txt for descriptions and try to run it.


2.  Your database server may not be running.  Check that the
   database server referred to by the "sqlalchemy.url" setting in
   your "development.ini" file is running.


After you fix the problem, please restart the Pyramid application to
try it again.
"""

rm {PROJECT_NAME}/models/default.py



STEP 6: Creating database migrations


alembic -c development.ini revision --autogenerate -m "init"


alembic -c development.ini upgrade head


initialize_{PROJEECT_NAME} development.ini






STEP 7 Running Server


pserve development.ini


the app can be accessed through the url http://localhost:6543/











       Popular use-cases and examples of RESTFUL APIs. Click on the link to know more: https://github.com/ramses-tech/ramses-example


The major benefits of the Pyramid are:




  1. Pyramid provides ample guidance for file bundling as compared to Django, thus packaging of your projects is done in a more full-proof manner. This provides a safety net, especially for new developers.


  2. It allows scalability of applications rapidly, with robust API support, URL mapping, and heavy extensibility via add ons.


  3. It supports all supported versions of Python.




The major drawbacks of the Pyramid are:


  1. Pyramid’s chameleon template syntax is relatively complicated.
  2. XHTML structuring, parsable by editors, can seem foreign and complex to those migrating from Django.




## 4.  Falcon:

A high-performance web framework focused on quality control. It was built as a bare metal framework that has been optimized for microservices. Through WSGI compliance, it’s made for compatibility with numerous servers and platforms.


Curated by Kurth Griffiths in 2013, it has garnered dedicated community support that provides extensive input. Companies like LinkedIn and Rackspace have been utilizing the framework for various projects.


Documented on Github, it has shipped 43 updates since its launch and is currently sitting on the version 14.1.




The code snippets below showcase: An ultimate API guide to fetch data from server through “get" HTTP method:



STEP 1: Project setup

$ mkdir look
$ cd look
$ virtualenv .venv
$ source .venv/bin/activate
$ pip install falcon

It’s customary for the project’s top-level module to be called the same as the project, so let’s create another “look” folder inside the first one and mark it as python modules by creating an empty __init__.py file in it:
$ mkdir look
$ touch look/__init__.py
Let’s move onto the next step,  let’s create a new file that will be the entry point into your app:
$ touch look/app.py
The file hierarchy should now look like this:
look
├── .venv
└── look
   ├── __init__.py
   └── app.py





STEP 2 : Hosting the app

Now that you have a simple Falcon app, you can take it for a role with a WSGI server. Python includes a reference server for self-hosting, but let’s use something more robust that you might use in production.


Now, open app.py in your favorite text editor and add the following lines:
import falcon
api = application = falcon.API()

This code creates your WSGI application and aliases it as api


Open a new terminal and run the following:
$ source .venv/bin/activate
$ pip install gunicorn
$ gunicorn --reload look.app
(Note the use of the –reload option to tell Gunicorn to reload the app whenever its code changes.)
If you are a Windows user, Waitress can be used in lieu of Gunicorn, since the latter doesn’t work under Windows:
$ pip install waitress
$ waitress-serve --port=8000 look.app:api
Now, with a different terminal, try querying the running app with curl:
$ curl -v localhost:8000
You should get a 404. That’s actually fine, because we haven’t specified any routes yet. Falcon includes a default 404 response handler that will fire for any requested path for which a route does not exist.
While the curl gets the job done, it can be a bit crufty to use. HTTPie is a modern, user-friendly alternative. Now let’s install HTTPie and use it from now on:
$ source .venv/bin/activate
$ pip install httpie
$ http localhost:8000

STEP 3 : Creating Resources

Now you have to create a new module,images.py next to app.py, and add the following code to it:


import json
import falcon
class Resource(object):


   def on_get(self, req, resp):
       doc = {
           'images': [
               {
                   'href': '/images/Screen.png'
               }
           ]
       }

# Create a JSON representation of the resource
      resp.body = json.dumps(doc, ensure_ascii=False)

# The following line can be deleted because 200 is the default
      # status is returned by the framework, but it is included here to
       # illustrate how it may be overridden as needed.
       resp.status = falcon.HTTP_200

As you can configure, Resource is just a regular class. You can name the class anything you like. Falcon uses duck-typing, so you don’t have to inherit from any sort of special base class.
The image resource above defines a singular method, on_get(). For any HTTP method you want your resource to support, simply add an on_*() method to the class, where * is any one of the standard HTTP methods, lowercase (e.g., on_get(), on_put(), on_head(), etc.).



import falcon


from .images import Resource
api = application = falcon.API()
images = Resource()
api.add_route('/images', images)
Now, when a request comes in for /images, Falcon will call the responder on the images resource that corresponds to the requested HTTP method.
Let’s try it. Restart Gunicorn (unless you’re using --reload), and send a GET request to the resource:
$ http localhost:8000/images
You should receive a 200 OK response, including a JSON-encoded representation of the “images” resource.








Don’t miss out on Falcon Docs for more detailed and in-depth research and knowledge:  https://falcon.readthedocs.io/en/stable/index.html


Popular organizations adapting Falcon for use-cases and real-world applications can be checked out using this link:


https://github.com/falconry/falcon/wiki/Who's-using-Falcon%3F


The major benefits of Falcon are:




  1. Falcon is OS agnostic and is focusing on running efficiently on hardware with framework flexibility.


  2. The framework is compatible with Python’s version 2.6, 2.7, and 3.4+.


  3. Source Code development is tested extensively for errors. Falcon uses only two third-party dependencies.


  4. Using its default configuration, Falcon can make up to 19x more requests per second than Django under identical conditions.




The major drawbacks of Falcon are:


  1. It is not suitable for HTML pages.
  2. It lacks a built-in web server.
  3. It is less comprehensive than frameworks such as Flask.




Disclosure:

In the end, you have a pool of options to choose from when you are planning to build REST APIs through open-source frameworks in Python. You can customize your options as per your project requirements as I have enlisted the pros and cons associated with these web frameworks in depth.