Last active
August 29, 2015 14:17
-
-
Save jpanganiban/c507f4091600fef5816c to your computer and use it in GitHub Desktop.
MVC pattern.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, render_template | |
app = Flask(__name__) | |
@app.route('/<user_id>/posts') | |
def api_posts(user_id): | |
"""Displays a page that returns all the posts created by this user.""" | |
# !IMPORTANT | |
ctx = {} | |
# `first_or_404` is a useful shortcut to: | |
# user = User.query.filter_by(id=user_id).first() | |
# if not user: | |
# abort(404) | |
user = User.query.filter_by(id=user_id).first_or_404() | |
ctx['user'] = user | |
ctx['posts'] = user.posts | |
return render_template('user_posts.html', **ctx) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
In this example, I won't be using the `db.relationship` function but instead | |
implement the entry associations manually by hand. | |
The obvious advantage to this route (vs using the `db.relationship` function) | |
is the explicitness (explicit over implicit). Another is lazy-loading (multiple | |
SELECT queries vs a single JOINED query). This can be done with the `db.relationship` | |
function by adding a `lazy=True`. | |
If you look deep in the `db.relationship` function implementation, setting the | |
`lazy` option implements it in this same exact way (lazy functions calling another | |
SELECT query). It can also be configured to do an eager load as well. | |
The `db.relationship` function has one big advantage though: Declaration on what to | |
do with the orphan objects (ie. deleting the objects if the parent is deleted). | |
See http://pythonhosted.org/Flask-SQLAlchemy/models.html#one-to-many-relationships | |
""" | |
from flask.ext.sqlalchemy import SQLAlchemy | |
db = SQLAlchemy() | |
class User(db.Model): | |
id = db.Column(db.Integer, primary_key=True) | |
username = db.Column(db.String(255), unique=True) | |
# Manually implement associations. Use of these attributes will | |
# `lazy-load` the value. Effectively making another query as | |
# opposed to having a single query with a join (eagerly-loaded). | |
# Here's a link about it: https://en.wikipedia.org/wiki/Lazy_loading. | |
# | |
# The `@property` makes this function behave like an attribute but | |
# its value is lazy-loaded. | |
@property | |
def posts(self): | |
"""Returns all the posts this user created.""" | |
return Post.query.filter_by(user_id=self.id).all() | |
class Post(db.Model): | |
id = db.Column(db.Integer, primary_key=True) | |
user_id = db.Column(db.Integer, index=True, unique=False) | |
content = db.Column(db.Text) | |
# Similar to the example above but implements the forward association. | |
# And this is also lazily-loaded. | |
@property | |
def user(self): | |
"""Returns the user that owns this post.""" | |
return User.query.filter_by(id=self.user_id).first() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
Here's a new pattern I've been experimenting with. I got this idea from | |
ReactJS components concept. This one however, implemented with Flask macros. | |
Read about web components: | |
http://webcomponents.org/presentations/complementarity-of-react-and-web-components-at-reactjs-conf/ | |
--> | |
{% macro PostInfo(post) %} | |
<span class="author">{{ post.user.username }}</span> | |
<span class="publication-date">{{ post.created_at }}</span> | |
{% endmacro %} | |
{% macro Post(post) %} | |
<div class="info"> | |
{{ PostInfo(post) }} | |
</div> | |
<div class="content"> | |
{{ post.content }} | |
</div> | |
{% endmacro %} | |
<!doctype html> | |
<html> | |
<body> | |
<div id="posts"> | |
{% for post in posts %} | |
<div class="post"> | |
{{ Post(post) }} | |
</div> | |
{% endfor %} | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment