Skip to content

Instantly share code, notes, and snippets.

@singingwolfboy
Created November 20, 2014 22:43
Show Gist options
  • Save singingwolfboy/7362f19ebb980bb29922 to your computer and use it in GitHub Desktop.
Save singingwolfboy/7362f19ebb980bb29922 to your computer and use it in GitHub Desktop.
I'm trying to set a relationship between User and UserEmail so that when I reference user.emails, the first email in the list is always the primary email. However, I'm getting `ProgrammingError: missing FROM-clause entry for table "app_user"` when I try to reference User.emails. How can I make this work? I might be going about this all wrong...
# coding=utf-8
from __future__ import unicode_literals, division
import sqlalchemy as sa
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from werkzeug.security import generate_password_hash, check_password_hash
Base = declarative_base()
class User(Base):
__tablename__ = "app_user"
id = sa.Column(sa.Integer, primary_key=True)
username = sa.Column(sa.String(255), unique=True, nullable=False)
password_hash = sa.Column(sa.String(255))
primary_email = sa.Column(sa.String(255))
@hybrid_property
def email(self):
"""
This is the object associated with the primary email.
"""
pes = [e for e in self.emails if self.primary_email == e.email]
if len(pes) < 1:
raise ValueError("missing primary email for user {}".format(self))
if len(pes) > 1:
raise ValueError("multiple primary emails for user {}".format(self))
return pes[0]
@email.expression
def email(cls):
return (
UserEmail.query
.join(cls)
.where(cls.primary_email == UserEmail.email)
)
@property
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
def __unicode__(self):
return self.username
class UserEmail(Base):
__tablename__ = "app_user_email"
id = sa.Column(sa.Integer, primary_key=True)
email = sa.Column(sa.String(255), nullable=False, unique=True)
user_id = sa.Column(sa.Integer, sa.ForeignKey(User.id))
user = relationship(User, backref=backref(
"emails",
order_by=(User.primary_email == email),
))
@property
def primary(self):
return self.user.primary_email == self.email
def __unicode__(self):
return self.email
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment