Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Python

Framework Pyramid: First steps

5.00/5 (2 votes)
23 Feb 2016CPOL5 min read 6.4K  
This document aims to demonstrate how the application here called PYRAMID was developed. In fact, this is only a test application, developed as training for learning the Pyramid framework using the Python programming language.

What is this?

This document aims to demonstrate how the application here called PYRAMID was developed. In fact, this is only a test application, developed as training for learning the Pyramid framework using the Python programming language. Moreover, the simplistic way, the integration is done with SQLAlchemy, which is a framework itself to interact with the database.

Structure of files and directories

__init__.py – Settings.

models.py – Layer access to data.

scripts – Where to find the upgrade scripts and application maintenance.

static– Where are the static files.

templates – View files.

tests.py – automated tests.

views.py – application business layer.

 

Installation

Such a configuration is to be done at the Linux machine. The machine in use is Centos version 7. If you use another type of the Linux operating system, it is necessary to review the syntax adopted.

 

Run the following steps:

 

1. yum install sqlite-devel git

2. virtualenv egito

3. cd egito

4. bin/activate ou  '. bin/activate'

5. pip install "pyramid==1.6"

6. bin/pcreate -s alchemy  tutorial

7. rm -rf tutorial/*

8. git clone https://github.com/wagnerwar/piramid.git tutorial

9. cd tutorial/

10. python setup.py develop

11. cd ../

12. bin/initialize_tutorial_db tutorial/development.ini

If the application is installed corretly, go to http://localhost:6543.

if the installation is successfully, will appear this:

 

Home

 

Data Model

 

File models.py:

class Video(Base):
        __tablename__ = 'video'
        id = Column(Integer, primary_key=True)
        name = Column(Text)
        description = Column(Text)
        price = Column(Float)

    Index('my_index', Video.name, unique=True, mysql_length=255)

 

File scripts/initializedb.py:

 

def main(argv=sys.argv):
        if len(argv) < 2:
            usage(argv)
            config_uri = argv[1]
            options = parse_vars(argv[2:])
            setup_logging(config_uri)
            settings = get_appsettings(config_uri, options=options)
            engine = engine_from_config(settings, 'sqlalchemy.')
            DBSession.configure(bind=engine)
            Base.metadata.create_all(engine)
            with transaction.manager:
                model = Video(name='one', price=1)
                DBSession.add(model)

 

Consideration is given to the above two lines, which is made to insert a record for test purposes.

 

Creation ot tables

 bin/initialize_tutorial_db tutorial/development.ini -- Where 'tutorial/development.ini' is the file settings.

As seen above, the Video class represents the video table with the following attributes: id, name, description and price. The SqlAlchemy framework allows manipulate objects that represent the data. That is why, You do not need to know the structure of the data, only know how to use the abstraction layer of the data. The same data can be in SQLite or POSTGRESQL; no matter, how to manipulate them is the same. 


An index my_index call associated with the video table was created.

 

Register

 

File __init__.py

 

def main(global_config, **settings):
        config.include(videos_include, route_prefix='/videos')
                    
    def videos_include(config):
        config.add_route('register', '/register')

 

As seen above, are set all paths starting with 'videos /' within the videos_include function.
For example, when we typed 'videos / register', will be charged to view register, the contents of which follows below, in views.py file.

 

File views.py

 

@view_config(route_name='register',renderer='templates/reg.pt')
    def register(request):
        save_url = request.route_url('register')
        request.route_url('query')
        if  request.params:
            print('RUN')
            nome = request.params['name']
            description = request.params['description']
            price = request.params['price']
            new_video = Video(name=nome,description=description,price=price)
            try:
                DBSession.add(new_video)
                return HTTPFound(location=request.route_url('query'))
            except DBAPIError:
            return Response("ERRO DB")
        else:
            print('DO NOT RUN')
            return {'save_url': save_url,'project': 'tutorial'}

 

As seen above, the view called 'register' renders the template 'templates / reg.pt'. The function register addresses the requests and responses of this URI (understood as the path of a URL, for example: http: // localhost / videos / register).

Note that if there are parameters in the request, the system attempts to register a new video. If there are no parameters simply displays the form for adding a new video.

Note that in each view, the 'return' always returns the variables that go to the template. For example, function register () defined that 'save_url' is equivalent to the value of save_url local variable ({return 'save_url': save_url}). Therefore, the value is available in the template below (<form action = "$ {save_url}" method = "GET">.

 

Template file: templates/reg.pt (relevant section )

 

<div class="content">
    <h1><span class="font-semi-bold">Register of the videos</span></h1>
    <form action="${save_url}" method="GET">
    <label>Name:<br>
    <input type="text" name="name" value="" /><br>
    </label>
    <label>Description:<br>
    <input type="text" name="description" value="" /><br>
    </label>
    <label>Price:<br>
    <input type="text" name="price" value="" /><br>
    </label>
    <label>
    <input type="submit" value="Register" style="margin-top: 1.2em;">
    </label>
    </form>
    </div>

 

In the middle of a large HTML code between HTML and BODY tags, after the HEAD tag, following up what really interests us.

 

Now, is to doing test. (http://192.168.56.101:6543/videos/register)

 

Register

 

Query

 

File __init__.py

 

def videos_include(config):
        config.add_route('query', '/')

 

Now, in the above excerpt was set new route. That is, when we type in the address bar "videos /" we will be redirected to the view 'query'. Setting this view is as follows:

 

File views.py

 

@view_config(route_name='query',renderer='templates/query.pt')
        def consulta(request):
            videos = DBSession.query(Video).all()
            url_edit = request.route_url('edition')
            url_cad = request.route_url('register')
            return {'videos': videos,'url_edit': url_edit,'url_cad': url_cad}

 

As the above code, I seek all records video table to display them in a list.

File template: 'templates/query.pt' (relevant section)

 

<div class="content">
    <h1>Listing videos</h1>
    <a tal:attributes="href string:${url_cad}"><button>REGISTER</button></a>
    <div tal:repeat="item videos">
    <div class="vido">
    <a tal:attributes="href string:${url_edit}?&id=${item.id} "><strong>Name: </strong><span tal:content="string:${item.name}" /></a><br />
    <strong>Description: </strong><span tal:content="string:${item.description}" /><br />
    <strong>Price: </strong><span tal:content="string:${item.price}" /><br />
    </div>
    </div>
    </div>
    </div>

 

Above the list of videos.

Image 3

Edition

 

File __init__.py

 

def videos_include(config):
        config.add_route('edition', '/edit')

 

Following up, setting the route 'videos / edit'.

 

File views.py

 

@view_config(route_name='edition',renderer='templates/edition.pt')
        def editar(request):
            save_url = request.route_url('edition')
            dell = request.route_url('delete')
            id = request.params['id']
            video = DBSession.query(Video).filter_by(id=id).one()
            if 'nome' in request.params.keys():
                try:
                    print("RUN")
                    name = request.params['name']
                    description=request.params['description']
                    price=request.params['price']
                    dados = DBSession.query(Video).filter_by(id=id).update({'name': name,'description': description,'price': price})
                    return HTTPFound(location=request.route_url('query'))
                except Exception:
                    return Response('ERROR DB')
                else:
                    print("nao passou")
                    return {'save_url': save_url,'video': video,'dell': dell}

 

In this view, it verifies that the parameters that identify the request relates will be submitting a form. If yes, it is made to update the video in question, identified by 'id' attribute. If not, the system display  a form with fields for editing the registry.

 

template file: 'templates/edition.pt' (Relevant section)

 

<div class="content">
    <h1><span class="font-semi-bold">EDITION</span> <span class="smaller">Videos</span></h1>
    <form action="${save_url}" method="GET">
    <label>Nome:<br>
    <input type="text" name="name" value="${video.name}" /><br></label>
    <label>Descricao:<br>
    <input type="text" name="description" value="${video.description}" /><br>
    </label><label>Preco:<br>
    <input type="text" name="price" value="${video.price}" /><br>
    </label>
    <label>
    <input tal:attributes="type string:hidden; name string:id; value string:${video.id}">
    <input type="submit" value="Edit" style="margin-top: 1.2em;">
    <a tal:attributes="href string:${dell}?id=${video.id}"><input type="button" value="Delete" style="margin-top: 1.2em;"></a>
    </label>
    </form>
    </div>

 

Follows up, display of video fields to update.

Image 4

Delete

File __init__.py

 

def videos_include(config):
    config.add_route('delete', '/del')

 

Above, the route setting to 'videos / del'

 

File views.py

 

@view_config(route_name='delete')
    def excluir(request):
    if request.params:
        try:
            id=request.params['id']
            DBSession.delete(DBSession.query(Video).filter_by(id=id).first())
            return HTTPFound(location=request.route_url('query'))
            except Exception:
                return Response("ID NOT KNOW")
    else:
        return Response("Where is the ID?")

 

If any 'id' parameter in the request, the requested video is excluded. If there is no video identified by 'id', then
the system displays the following message: "ID NOT KNOW '. If there is no parameter 'id', then the following message appears: "Where is the ID?"

 

Running the application

 

To run the application, you must access the directory root of your virtual environment (In our example, within Egypt folder). Then, considering that you are also using Centos 7, run the following command:

bin/pserve tutorial/development.ini

 

You will see output similar to this:

Starting server in PID 11533.
serving on http://0.0.0.0:6543
 

 

The output above indicates that the application is available on port 6543. But port where? The machine that is hosting this application. If your local machine, then to test, just type in your address bar: http: // localhost: 5432 / videos /.

 

Dealing with templates

 

The Pyramid framework uses the following template for languages: TAL, METAL and Mako. These languages may be used together. In our example, it is only used TAL language, to access the value of some variables and perform iterations in some listings. Template Language is the language used to program in static files (in HTML format).

 

References

 

https://media.readthedocs.org/pdf/sqlalchemy/rel_1_0/sqlalchemy.pdf

http://docs.pylonsproject.org/en/latest/

https://www.owlfish.com/software/simpleTAL/tal-guide.html
 

 

 

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)