Slide 1

Slide 1 text

Web development Code to deployment A S L Devi PyCon India, 2012

Slide 2

Slide 2 text

Request - response cycle HTTP server Browser Views Models Database URL Routing Templates

Slide 3

Slide 3 text

What are we going to do ● Get introduced to Flask and templates ○ write a simple hello world app ● Simple Quotes website ○ design urls ● Get into SQLAlchemy - the database stuff ○ design the quote model ○ see how SQLAlchemy works, on terminal ○ get the basic website working

Slide 4

Slide 4 text

More to do ... ● Learn about SQLAlchemy relationships ○ get tags working ● Add AJAX ○ get votes working ● Get ready for Heroku ○ push and deploy !!

Slide 5

Slide 5 text

"Hello World!" in Flask from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello World!' if __name__ == '__main__': app.run()

Slide 6

Slide 6 text

"Hello" app with templates ● A template is simply a text file, which can generate any text-based format like HTML, XML etc ● Jinja2 ○ templating language for Python ○ fast, widely used, designer friendly, easy-to-debug and secure ○ template inheritance support

Slide 7

Slide 7 text

Now, let's build Quottit A simple website of quotes to post, vote, tag, list quotations. ● / ● /add ● /t/ ● /a/ ● /v/

Slide 8

Slide 8 text

Quote Model in Flask-SQLAlchemy class Quote(db.Model): __tablename__ = 'quotes' id = db.Column(db.Integer, primary_key=True) text = db.Column(db.Text, nullable=False) author = db.Column(db.String(128)) votes = db.Column(db.Integer, default=0) created_at = db.Column(db.DateTime, nullable=False, default=db.func.now())

Slide 9

Slide 9 text

SQLAlchemy - Insert, Delete, Select, Update >>> q = Quote(text='...', author='...') >>> db.session.add(q) >>> db.session.commit() >>> db.session.delete(q) >>> db.session.commit() Methods operating on BaseQuery Object all(), get(), get_or_404() filter(), filter_by() update() order_by(...), group_by() limit()

Slide 10

Slide 10 text

List all quotes @app.route('/') def index(): quotes = Quote.query.all() return render_template('index.html', quotes=quotes)

Slide 11

Slide 11 text

Add quotes now... class QuoteForm(Form): text = TextAreaField('Quote', [validators.Required()]) author = TextField('Author', [validators.Required()]) In Template: {{form.text.label}}{{form.text(rows=3, cols=50)}} {{form.author.label}}{{form.author(size=50)}}

Slide 12

Slide 12 text

In the view: @app.route('/add', methods=['POST']) def add(): form = QuoteForm(request.form) if form.validate(): author = slugify(form.author.data) q = Quote(text=form.text.data, author=author) db.session.add(q) db.session.commit() ... if method is GET, data can be accessed as in request. args('') Get the data and validate

Slide 13

Slide 13 text

Tags - Many-to-many relationships quote_tags = db.Table('quote_tags', db.Column('quote_id', db.Integer, db.ForeignKey('quotes. id')), db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')) ) class Tag(db.Model): __tablename__ = 'tags' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), nullable=False) class Quote(db.Model): ... tags = db.relationship('Tag', secondary='quote_tags', backref='quotes')

Slide 14

Slide 14 text

Add votes through AJAX In the View: @app.route('/v/', methods=['POST']) def vote(): rf = request.form vote, qid = int(rf.get('vote')), int(rf.get('qid')) q = Quote.query.get_or_404(qid) if q and vote in (1, -1): Quote.query.filter_by(id=qid).update({'votes':q.votes+vote}) db.session.commit() return jsonify(votes=q.votes) In the template: $.post('/v/', {'qid': parseInt(qid), vote: parseInt(vote)}, function(d){ update_vote(qid, d['votes']); });

Slide 15

Slide 15 text

Why? ● Agile deployment for Python, Ruby, Java etc ● Get up and running in minutes. ● Deploy instantly with git ● Never think about servers, instances or VMS! ● Scaling is a single command thing How? $ echo "web: python run.py" >> Procfile $ pip freeze > requirements.txt #add psycopg too $ heroku login $ heroku create $ git push heroku master Ready to deployment - Heroku

Slide 16

Slide 16 text

More on Heroku $ heroku rename NEWAPPNAME #rename your app $ heroku logs # what's happenening? $ heroku ps # what are running $ heroku addons:add heroku-postgresql --app $ heroku addons # list the accessories $ heroku config # see/set the configuration variables $ heroku run bash # shell on the server in your app's env $ heroku releases # revision history of deployments $ heroku rollback # oops, revert back the last release $ heroku restart $ heroku scale web=3 worker+1

Slide 17

Slide 17 text

Deploying with gunicorn Let's use gunicorn as the web server instead of the Flask's default HTTP server, which is intended for development. $ echo "gunicorn" >> requirements.txt $ echo "web: gunicorn run:app -b 0.0.0.0:$PORT" > Procfile $ git commit Procfile requirements.txt -m "use gunicorn" $ git push heroku master Yeah, It's that simple !

Slide 18

Slide 18 text

Questions?

Slide 19

Slide 19 text

Thank You! @asldevi