Skip to content

Instantly share code, notes, and snippets.

View tachyondecay's full-sized avatar

Kara Babcock tachyondecay

View GitHub Profile
@tachyondecay
tachyondecay / create_app.py
Created August 14, 2020 21:07
Host matching with Flask
def create_app():
"""Factory for the application."""
config_name = os.getenv('FLASK_ENV', 'production')
app = Flask(
'lemonade_soapbox',
static_folder='assets',
static_host=os.getenv('MAIN_HOST'),
host_matching=True,
)
@tachyondecay
tachyondecay / api.py
Last active July 21, 2020 19:04
Refresh CSRF token after 1 hour
@bp.route('/csrf/')
@login_required
def get_csrf():
return csrf.generate_csrf()
@tachyondecay
tachyondecay / description.md
Last active June 23, 2020 18:51
Count across multiple association tables

Solution

I needed to use the [as_scalar()][1] method on the subquery, which turns the SELECT expression into a regular column:

a_q = db.session.query(func.count(tag_relationships['Article'].c.post_id)).select_from(tag_relationships['Article']).filter(tag_relationships['Article'].c.tag_id == Tag.id).subquery()
r_q = db.session.query(func.count(tag_relationships['Review'].c.post_id)).select_from(tag_relationships['Review']).filter(tag_relationships['Review'].c.tag_id == Tag.id).subquery()
db.session.query(Tag, a_q.as_scalar(), r_q.as_scalar()).group_by(Tag.id).order_by(Tag.handle).limit(10).all()
@tachyondecay
tachyondecay / README.md
Last active February 12, 2024 06:11
Host matching in blueprints at reg time + free static endpoint creation

What This Does

Let's say you want to serve 2 domains, example1.com and example2.com, from the same app (i.e., using host matching). You also want your static assets for each domain to be served from those domains, e.g., example1.com/static/ and example2.com/static/. You can almost achieve this in Flask, but not quite.

This code extends Flask's Blueprint class to make registering hostnames onto a blueprint painless and ensure static assets appear to be served from the appropriate hostname.

Default Flask Behaviour

By default, Flask supports host matching at the app-level by passing host_matching=True and a hostname for static_host when initializing the app. However, there are drawbacks to the current support, especially when using blueprints:

  1. To match all routes on a blueprint to a host, you must pass the host parameter to every route decorator for that blueprint.
  2. The app's static files will always be served
@tachyondecay
tachyondecay / models.py
Created July 16, 2018 20:13
quick example
from app import app, db # DB is your Flask-SQLAlchemy object
# By default this will correspond to a table named "ticket" in your db
# You can override this, of course (see the docs) to point to any tablename
class Ticket(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime, nullable=False)
severity = db.Column(db.Integer, nullable=False, default=0)
message = db.Column(db.String)
@tachyondecay
tachyondecay / models.py
Last active March 19, 2024 19:08
Tags in Flask via SQLalchemy and association proxies
from app import db
from sqlalchemy import desc, event, func, orm
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy_utils import ArrowType, auto_delete_orphans
from slugify import slugify_unicode
tags = db.Table('tag_associations',
db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')),
db.Column('article_id', db.Integer, db.ForeignKey('articles.id')))
@tachyondecay
tachyondecay / twitter.css
Created May 22, 2016 16:00
Stylish sheets
@namespace url(http://www.w3.org/1999/xhtml);
@-moz-document domain("twitter.com") {
.dashboard-right {
visibility: hidden;
}
.js-moments-tab {
visibility: hidden;
width: 0px;
}
class Supplier(db.Model):
"""A supplier of consignment items."""
__tablename__ = 'consignment_suppliers'
id = db.Column(db.Integer, primary_key=True)
supplier_name = db.Column(db.String(200),
unique=True,
info={'label': 'Business name',
'filters': [lambda x: x or None]})
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
@tachyondecay
tachyondecay / logging_config.py
Created January 7, 2016 23:54
Logging for Flask app
logging_config = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
},
"handlers": {
@tachyondecay
tachyondecay / datetime-local.py
Last active March 8, 2024 09:18
DateTime WTForms field that assumes input is in local time and converts to UTC for storage
# Requires Arrow package
class DateTimeWidget:
"""Widget for DateTimeFields using separate date and time inputs."""
def __call__(self, field, **kwargs):
id = kwargs.pop('id', field.id)
date = time = ''
if field.data:
dt = arrow.get(field.data).to(current_app.config['TIMEZONE'])
date = dt.format('YYYY-MM-DD')