9: Advanced Topics

Expectations

From here on out, your project is going to vary from everyone else’s. Once your models are done, you’ve now got to build out each view and template that will serve the workflow of your MVP. Work with your teacher to identify what your MVP needs to do, (we’ll call this your requirements based off of the SRS stage of the IEEE software lifecycle). Once we work out what exactly you’re building in your module, we’ll populate your Trello backlog with loads of tasks. And as we solve those weird tasks, we’ll start to build the collection of topics below.

Learning Targets

  • I can research and hack together an MVP.

Session

Decorators

http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/

The term decorators in programming refers to a sort of flag or notice put at the start of a method to signal some sort of special treatment. We use @login_required to trigger Flask-Security’s verification that the user is carrying the encrypted token from our system given to a confirmed user. I would imagine verification of authority and privileges is the most common reason to use a decorator in Flask. We use them in Java to notify the system we’re overriding a parent’s method.

Forms

The form is our primary method of collecting information from the user. Depending on your application's need, you may need to looking closely into wtforms. Meanwhile, here are a few recipes that have been requested.

In case you forgot what a drop-down looks like?

When filling out a form, you may want to have a drop-down of a user's friends or some other set of data unique to that user. How can you provide those dynamic options within a form template?

The most typically recommended answer is the QuerySelectField.

And what if you want one drop-down to populate the options of another dropdown?

Build Options From a View

Just use a SelectField with no real options and populate them after you build the form.

https://stackoverflow.com/questions/46921823/dynamic-choices-wtforms-flask-selectfield

Placeholders

https://stackoverflow.com/questions/9749742/python-wtforms-can-i-add-a-placeholder-attribute-when-i-init-a-field

Examples:

Captcha

SQLAlchemy and Databases

backref VS back_populates

http://docs.sqlalchemy.org/en/latest/orm/backref.html#relationships-backref

Two back_populates equals one backref. Using backref declares a two-way relationship. It’s more efficient than dropping a back_populates on both ends of the relationship but I prefer it because I’ve been confused too many times staring at a class wondering about its relationships unaware that another class has declared a relationship backref in a different file.

Relationship Loading: Lazy?

http://docs.sqlalchemy.org/en/latest/orm/loading_relationships.htmlLet’s say you want to query the database for a user’s contacts with a built-in relationship such as current_user.contacts. You can get a list back from the database with just that one command. However, what if you know you’ll always need additional filters on that query. You don’t want the results quite so fast, instead you’d like the SQLAlchemy query not to complete its task but rather to keep the search open and ready for additional filtering or sorting.

Command Line Interface

flask shell

This is a really useful skill we should go over as it helps us test and figure out where things go wrong.

flask shell

if python just said it doesn't know what that is, then you need this line: from extensions import db

from user.models import User

my_users = User.query.all()

look at your user(s): my_users my_users[0].email

my_users[0].first_name

Talking to Postgres

Let's make sure we can login directly to our database. You can skip this step if you're, say, in the midst of a hackathon, the app is working, and you've got to keep moving. In the long-run, it's critical you know how to flex control over your database directly.

If you're using Terminal, bash or PowerShell, you should be able to type psql to open a command-line version of PostgreSQL. You can also use a friendlier interface like pgAdmin, though I recommend making the effort to explore both. You'll need to specify your user when accessing psql. Specifying your user can vary a lot depending on how you approach it. Good thing you know how to Google.

Linux:

sudo service postgresql start psql (try listing the current databases) \l (if you need to quit) \q

If you’re the superuser using sudo -i then you’ll be on the root account (don’t do that). Postgres has a built-in admin you can log into with su - postgres and then psql (you shouldn’t need that but it’s useful).

You can edit accounts' psql access and credentials with stuff like:

ALTER ROLE ubuntu WITH PASSWORD 'ubuntu';

You probably won’t need this very often, but it’s important to know if you want to understand how your app works. Launch psql and be very careful as you tiptoe through our database:

(connect to our database, which in this example is named “db”) \c db

(check out the tables in our database) \dt

(see what we’ve got in our post table) SELECT * FROM post;

If there are no posts, we’re going to create the first one, which will have the ID of zero. If there are posts already, we’re going to create one with the next highest number.

(let’s add a new record of a post)

INSERT INTO post (id, user_id, title, subtitle, body, slug, live) VALUES (0, 0, “Some title”, “Some subtitle”, “Some body”, “someslug”, True);

(let’s quit psql) \q

Launch your app and check it out. Not pretty, right?

(go back into psql and connect to our db then let’s delete what we made)

DELETE FROM post WHERE id=0;

(make sure it’s gone) SELECT * FROM post;

Configuring Flask-Mail

https://pythonhosted.org/Flask-Mail/

This line needs to be in your settings.py:

SECURITY_EMAIL_SENDER = private.ADMIN_EMAIL

JavaScript

Confirmation Buttons

Just as we keep a custom.css file, your project should have a custom.js function. Something like this could be very handy. Now you can just add class=”confirmation” attribute to any <a></a> and it’ll have a JS-powered confirmation window.

$('.confirmation').on('click', function () {
return confirm('Are you sure?');
});

AJAX: Server Without Reloads

Actions of our app are triggered by routes in our view. If you type in the url of your site, /index, your browser sends a GET request to that route to the homepage route in your app. Your browser loads the page. But what if you want to avoid refreshing the page? What if you want to send a message from a modal window and press submit without losing your spot on the current page?

Passing Variables from Flask to JavaScript

Calling a JavaScript Method on a Button

<a onclick="hidePaidBills()" href="javascript:void(0);" data-toggle="tooltip" data-placement="top" title="hide paid"><i class="fa fa-eye"></i></a>

// HIDE PAID BILLS
function hidePaidBills(){
$('.bill-paid').each(function() {
$(this).hide();
})

Sending SMS Messages with Twillio

https://www.twilio.com/docs/sms/quickstart/python

Updating Dependencies

We use VirtualEnv as a sort of bubble that contains our version of Python, Flask, and all the many other libraries used. Each library is likely to see improvements and security fixes. It’s important to keep this codebase updated but it’s an awfully risky process. Updates might change how some of the libraries work and may force you to change or cause new bugs. Best practice is to keep a previous version of your requirements.txt handy and to build thorough unit tests.

Before asking pip to do a lot of work, you may want it upgrade it first: pip install --upgrade pip

Update all libraries (copied from StackOverflow)

sudo -H python3 -m pip freeze --local | grep -v '^-e' | cut -d = -f 1 | xargs -n1 sudo python3 -m pip install -U

Create a requirements document:

pip freeze > requirements.txt

Test to make sure the app works. If it doesn't, undo changes tracked by git to get you your previous version of the requirements.txt. Reinstall your dependencies based on all the previously recorded versions.

Unit Tests

http://flask.pocoo.org/docs/0.12/testing/

The most responsible way to build software is to start with unit tests. A script will mimic various types of users as they test every function on your site. The unit test will report when something acts differently than expected. I struggle with keeping to this discipline. A more sophisticated implementation of Flask’s unit test system will be the best sign of my own professional growth in this area.