Skip to content

Instantly share code, notes, and snippets.

@typehorror
Created November 28, 2012 21:19
Show Gist options
  • Save typehorror/4164619 to your computer and use it in GitHub Desktop.
Save typehorror/4164619 to your computer and use it in GitHub Desktop.
A solution I use on my flask project to store event related to any generic object to be later displayed on a feed.
from datetime import datetime
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import event
from app import db
class EventAssociation(db.Model):
__tablename__ = "events_association"
id = db.Column(db.Integer, primary_key=True)
discriminator = db.Column(db.String)
@classmethod
def creator(cls, discriminator):
return lambda events: EventAssociation(
events = events,
discriminator=discriminator)
@property
def parent(self):
return getattr(self, "%s_parent" % self.discriminator)
class Event(db.Model):
__tablename__ = "events_event"
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey("identities_user.id"))
author = db.relationship("User",
backref=db.backref("events", lazy="dynamic"))
creation_date = db.Column(db.DateTime, default=datetime.utcnow)
association_id = db.Column(db.Integer, db.ForeignKey("events_association.id"))
association = db.relationship("EventAssociation", backref="events")
parent = association_proxy("association", "parent")
class HasEvent(object):
@declared_attr
def event_association_id(cls):
return db.Column(db.Integer, db.ForeignKey("events_association.id"))
@declared_attr
def event_association(cls):
discriminator = cls.__name__.lower()
cls.events = association_proxy(
"event_association", "events",
creator=EventAssociation.creator(discriminator)
)
return db.relationship("EventAssociation",
backref=db.backref("%s_parent" % discriminator, uselist=False))
@classmethod
def __declare_last__(cls):
event.listen(cls, "before_insert", cls._before_insert)
event.listen(cls, "before_delete", cls._before_delete)
@staticmethod
def _before_insert(mapper, connection, target):
target.events = [Event(author=target.author)]
@staticmethod
def _before_delete(mapper, connection, target):
db.session.delete(target.events)
from app import db
from event_models import HasEvent
# HasEvent will ensure that on Comment or Post insert, an event object is generated
# and related to itself and its author
# (see HasEvent._before_insert and HasEvent_before_delete methods)
class Post(HasEvent, db.Model):
__tablename__ = 'post'
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey("identities_user.id"))
author = db.relationship("User", backref=db.backref("posts", lazy="dynamic"))
creation_date = db.Column(db.DateTime, default=datetime.utcnow)
content = db.Column(db.String)
class Comment(HasEvent, db.Model):
__tablename__ = 'comment'
id = db.Column(db.Integer, primary_key=True)
post_id = db.Column(db.Integer, db.ForeignKey("post.id"))
post = db.relationship("Post", backref=db.backref("comments", lazy="dynamic"))
author_id = db.Column(db.Integer, db.ForeignKey("identities_user.id"))
author = db.relationship("User", backref=db.backref("comments", lazy="dynamic"))
creation_date = db.Column(db.DateTime, default=datetime.utcnow)
content = db.Column(db.String)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment