Skip to content

Instantly share code, notes, and snippets.

@jstacoder
Last active February 10, 2017 23:53
Show Gist options
  • Save jstacoder/907d9e232a9f67f89c45 to your computer and use it in GitHub Desktop.
Save jstacoder/907d9e232a9f67f89c45 to your computer and use it in GitHub Desktop.
fun with python lambdas, print database tables and columns with a single line function using lambdas and sqlalchemy
print_tables =\
lambda\
BaseModel:\
''.join(
map(
lambda x:\
'\n{}\n{}\n'.format(
x[0],
x[1].__table__.c.keys()
),filter(
lambda x: not x[0].startswith('_'),
BaseModel._decl_class_registry.items()
)
)
)
from models import BaseModel
print print_tables(BaseModel)
# This file is just so the example will have a decent amount
# of output,it not needed for the above file to work,
# you just need some simple models
from sqlalchemy.ext.declarative import declarative_base,declared_attr
from functools import partial
from flask import current_app,json
from inflection import pluralize, underscore
from jinja2 import Environment
from bcrypt import checkpw,gensalt,hashpw
import sqlalchemy as sa
from dates import format_date
_engine = lambda DB_URI,echo=True: sa.create_engine(DB_URI,echo=echo)
def get_base():
base = declarative_base()
base._sess = sa.orm.scoped_session(sa.orm.sessionmaker(
)
)
return base
class classproperty(object):
def __init__(self,getter):
self.getter = getter
def __get__(self,instance,owner):
return self.getter(owner)
class DateMixin(object):
__abstract__ = True
@declared_attr
def date_added(self):
return sa.Column(sa.DateTime,default=sa.func.now())
@declared_attr
def date_modified(self):
return sa.Column(sa.DateTime,default=sa.func.now(),onupdate=sa.func.now())
class PasswordHashMixin(object):
#__abstract__ = True
_pwhash = sa.Column(sa.Text)
@property
def pwhash(self):
raise ValueError
@pwhash.setter
def pwhash(self,data):
self._pwhash = hashpw(data,gensalt())
def check_password(self,pw):
return checkpw(pw,self._pwhash)
class BaseModel(get_base()):
__abstract__ = True
_engine = None
_session = None
@declared_attr
def id(self):
return sa.Column(sa.Integer,primary_key=True)
@declared_attr
def __tablename__(self):
return pluralize(underscore(self.__name__))
@classproperty
def engine(cls):
if cls._engine is None:
BaseModel._engine = _engine(current_app.config.get('DATABASE_URI'))
cls.metadata.bind = cls._engine
return cls._engine
@classproperty
def session(cls):
if BaseModel._session is None:
BaseModel._session = BaseModel._sess()
BaseModel._session.bind=cls.engine
return BaseModel._session
@classproperty
def query(cls):
return cls.session.query(cls)
@classmethod
def get_all(cls):
return cls.query.all()
@classmethod
def get_new(cls,**kwargs):
return cls(**kwargs).save()
@classmethod
def get_by_id(cls,item_id):
return cls.query.filter(cls.id==item_id).first()
@classmethod
def get(cls,*args,**kwargs):
return cls.get_by_id(*args,**kwargs)
def save(self):
self.session.add(self)
self.session.commit()
return self
def update(self):
return self.save()
def delete(self):
self.session.delete(self)
return self in self.session.deleted and\
self.session.commit()
class Post(BaseModel):
_env = None
_context = {}
author_id = sa.Column(sa.Integer,sa.ForeignKey('app_users.id'),nullable=False)
author = sa.orm.relationship('AppUser',backref=sa.orm.backref('posts',lazy='dynamic'),uselist=False)
title = sa.Column(sa.String(255),nullable=False)#,unique=True)
_content = sa.Column(sa.Text)
use_jinja = sa.Column(sa.Boolean,default=False)
date_added = sa.Column(sa.DateTime,default=sa.func.now())
date_modified = sa.Column(sa.DateTime,default=sa.func.now(),onupdate=sa.func.now())
tags = sa.orm.relationship('Tag',lazy='dynamic',secondary="posts_tags")
comments = sa.orm.relationship('Comment',lazy='dynamic')
def __init__(self,*args,**kwargs):
if 'content' in kwargs:
self._content = kwargs.pop('content')
if 'tags' in kwargs and kwargs.get('tags'):
print kwargs.get('tags')
tags = kwargs.pop('tags')
if type(tags) == unicode:
tags = json.loads(tags)
print tags
print type(tags)
for t in tags:
if t is not None:
tag = Tag.get_by_id(int(t))
if tag:
self.tags.append(tag)
self._env = Environment()
self._context = {}
super(Post,self).__init__(*args,**kwargs)
def add_comment(self,*args,**kwargs):
comment = Comment(post_id=self.id,**kwargs).save()
return self
@property
def slug(self):
return self.title.lower().replace(' ','_').replace(':','').replace('-','').replace('.','')
@property
def content(self):
rtn = self._content
if self.use_jinja:
rtn = self._env.from_string(self._content).render(**self._context)
return rtn
@content.setter
def content(self,data):
self._content = data
self.update()
def to_json(self):
return dict(
title=self.title,
slug=self.slug,
content=self.content,
date_added=format_date(self.date_added),
id=self.id,
tags=[x.name for x in self.tags.all()],
comments=[x.to_json() for x in self.comments.all()],
author_id=self.author_id,
author=self.author.username
)
def _add_to_ctx(self,key,val):
self._context[key] = val
def __repr__(self):
return '<Post:{0}'.format(self.slug)
class Email(BaseModel):
__table_args__ = (
(
sa.UniqueConstraint('address','app_user_id'),
sa.UniqueConstraint('address','public_user_id'),)
)
address = sa.Column(sa.String(255))
user_data_id = sa.Column(sa.Integer,sa.ForeignKey('user_profiles.id'))
app_user_id = sa.Column(sa.Integer,sa.ForeignKey('app_users.id'))
user_type = sa.Column(sa.Enum('public','app',name='user_type'),default='public')
public_user_id = sa.Column(sa.Integer,sa.ForeignKey('public_users.id'))
def to_json(self):
return dict(
address=self.address,
user_id=getattr(self,self.user_id_col)
)
@property
def user_id_col(self):
return '{0}_user_id'.format(self.user_type)
@property
def user(self):
user_types = dict(app=AppUser,public=PublicUser)
return user_types[self.user_type].get_by_id(getattr(self,self.user_id_col))
class UserProfile(BaseModel):
first_name = sa.Column(sa.String(255))
last_name = sa.Column(sa.String(255))
age = sa.Column(sa.Integer)
date_added = sa.Column(sa.DateTime,default=sa.func.now())
location = sa.Column(sa.String(255))
emails = sa.orm.relationship('Email',backref=sa.orm.backref('user_profile'),lazy='dynamic')
def __repr__(self):
return (
'FirstName:{:^20}\nLastName:{:^20}\n'
'Age:{!s:^20}\nDate:{!s:^20}\nLocation:{:^20}\n'
).format(
self.first_name,self.last_name,
self.age,self.date_added,self.location
)
class AppUser(PasswordHashMixin,BaseModel):
emails = sa.orm.relationship('Email',lazy='dynamic')
username = sa.Column(sa.String(255),unique=True,nullable=False)
user_profile_id = sa.Column(sa.Integer,sa.ForeignKey('user_profiles.id'))
profile = sa.orm.relationship('UserProfile',uselist=False,backref=sa.orm.backref('user'))
def __repr__(self):
return str(self.username)
def __init__(self,*args,**kwargs):
if 'password' in kwargs:
self.pwhash = kwargs.pop('password')
if 'email' in kwargs:
email = [Email(address=kwargs.pop('email'),user_type='app').save()]
kwargs['emails'] = kwargs.get('emails') and (email + kwargs.pop('emails')) or email
super(AppUser,self).__init__(*args,**kwargs)
self.profile = UserProfile(id=self.id).save()
@property
def pwhash(self):
raise ValueError
@pwhash.setter
def pwhash(self,data):
self._pwhash = hashpw(data,gensalt())
def check_password(self,pw):
return checkpw(pw,self._pwhash)
def to_json(self):
return dict(
username=self.username,
id=self.id,
emails=[x.to_json() for x in self.emails.all()],
is_public=False
)
class Tag(BaseModel):
name = sa.Column(sa.String(255),unique=True,nullable=False)
description = sa.Column(sa.Text)
#relationships
posts = sa.orm.relationship('Post',
lazy='dynamic',
secondary='posts_tags'
)
def to_json(self):
return dict(
name=self.name,
description=self.description,
id=self.id
)
class Comment(BaseModel):
subject = sa.Column(sa.String(255))
post_id = sa.Column(sa.Integer,sa.ForeignKey('posts.id'))
parent_comment_id = sa.Column(sa.Integer,sa.ForeignKey('comments.id'))
date_added = sa.Column(sa.DateTime,default=sa.func.now())
content = sa.Column(sa.Text)
author_id = sa.Column(sa.Integer,sa.ForeignKey('app_users.id'))
author = sa.orm.relationship('AppUser',backref=sa.orm.backref('comments',lazy='dynamic'))
replys = sa.orm.relationship('Comment')
parent = sa.orm.relationship('Comment',remote_side='Comment.parent_comment_id',uselist=False)
post = sa.orm.relationship('Post')
def to_json(self):
return dict(
subject=self.subject,
post_id=self.post_id,
content=self.content,
author=self.author and self.author.username or '',
id=self.id,
children=[x.to_json() for x in self.replys],
parent=self.parent_comment_id,
date=format_date(self.date_added)
)
class PublicUser(BaseModel,PasswordHashMixin):
username = sa.Column(sa.String(255),unique=True,nullable=False)
email_id = sa.Column(sa.Integer,sa.ForeignKey('emails.id'))
email = sa.orm.relation('Email',foreign_keys='[PublicUser.email_id]')
def __init__(self,*args,**kwargs):
addr = None
if 'password' in kwargs:
self.pwhash = kwargs.pop('password')
if 'email' in kwargs:
addr = kwargs.pop('email')
self.email = Email.get_new(address=addr,user_type='public')
if not 'username' in kwargs:
kwargs['username'] = self.email.address
super(PublicUser,self).__init__(*args,**kwargs)
self.save()
self.email.public_user_id = self.id
self.email.save()
def to_json(self):
return dict(
username=self.username,
id=self.id,
email=self.email.address,
is_public=True
)
posts_tags =\
sa.Table(
'posts_tags',
BaseModel.metadata,
sa.Column('post_id',sa.Integer,sa.ForeignKey('posts.id')),
sa.Column('tag_id',sa.Integer,sa.ForeignKey('tags.id'))
)
Comment
['subject', 'post_id', 'parent_comment_id', 'date_added', 'content', 'author_id', 'id']
PublicUser
['_pwhash', 'username', 'email_id', 'id']
Tag
['name', 'description', 'id']
Post
['author_id', 'title', '_content', 'use_jinja', 'date_added', 'date_modified', 'id']
UserProfile
['first_name', 'last_name', 'age', 'date_added', 'location', 'id']
Email
['address', 'user_data_id', 'app_user_id', 'user_type', 'public_user_id', 'id']
AppUser
['_pwhash', 'username', 'user_profile_id', 'id']
@jstacoder
Copy link
Author

@cetanu of course it isn't, but it is cool. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment