Esempio n. 1
0
class Item(Base):
    __tablename__ = 'item'

    name = Column(String(250), nullable=False)
    id = Column(Integer, primary_key=True)
    description = Column(String(250))
    picture = image_attachment('ItemPicture')
    created_at = Column(
        DateTime, default=datetime.now(), onupdate=datetime.now())
    category_id = Column(Integer, ForeignKey('category.id'))
    category = relationship(Category)
    user_id = Column(Integer, ForeignKey('user.id'))
    user = relationship(User)

    @property
    def serialize(self):
        """Return object data in easily serializeable format"""
        return {
            'name': self.name,
            'description': self.description,
            'id': self.id,
            'category_id': self.category_id,
            'created_at': self.created_at,
            'creator_id': self.user_id,
        }
Esempio n. 2
0
class Antibody(Base):
    __tablename__ = 'antibody'
    name = Column(String(80), nullable=False)
    id = Column(Integer, primary_key=True)
    weight = Column(Float, nullable=False)
    target = Column(String(80), nullable=False)
    a_lot = relationship('AntibodyLot', cascade='all, delete-orphan')
    picture = image_attachment('AntibodyImg')
    user_id = Column(Integer, ForeignKey('user.id'))
    user = relationship(User)

    @property
    def serialize(self):
        try:
            url = self.picture.locate()
        except IOError:
            url = ''
        return {
            "antibody_id": self.id,
            "antibody_name": self.name,
            "molecular_weight": self.weight,
            "target": self.target,
            "picture_url": url,
            "user_id": self.user_id
        }
Esempio n. 3
0
class Something(Base):

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    cover = image_attachment('SomethingCover')

    __tablename__ = 'something'
Esempio n. 4
0
class Manything(Base):

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    covers = image_attachment('ManythingCover', uselist=True)

    __tablename__ = 'manything'
Esempio n. 5
0
class Publisher(db.Model, CRUDMixin):
    """
    Publisher model class with two back referenced relationships, titles and
    issues.

    Example: Marvel Comics, Image Comics
    """
    __tablename__ = 'publishers'
    #: IDs
    id = db.Column(db.Integer, primary_key=True)
    #: Attributes
    name = db.Column(db.String(255))
    #: Images
    logo = image_attachment('PublisherLogo')
    logo_bw = image_attachment('PublisherLogoBW')
    splash = image_attachment('PublisherSplash')
    #: Colors
    primary_color = db.Column(db.String(20), default='#aaaaaa')
    secondary_color = db.Column(db.String(20), default='#aaaaaa')
    #: Relationships
    titles = db.relationship(
        'Title',
        backref=db.backref('publisher', lazy='joined'),
        lazy='dynamic'
    )
    comics = db.relationship(
        'Issue',
        backref=db.backref('publisher', lazy='joined'),
        lazy='dynamic'
    )

    @classmethod
    def from_raw(cls, record):
        record = deepcopy(record)
        created = 0
        try:
            name = record.get('publisher')
            publisher = cls.query.filter_by(name=name).first()
            if not publisher:
                publisher = cls.create(name=name)
                created = created + 1
        except Exception, err:
            print 'Publisher failed creation: ', record.get('publisher')
            print 'Error: ', err
            db.session.rollback()
            publisher = None
        return (publisher, created)
Esempio n. 6
0
class Samething(Base):
    """Not S'o'mething, but s'a'mething."""

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    cover = image_attachment('SamethingCover')

    __tablename__ = 'samething'
Esempio n. 7
0
class Message(Base):
    __tablename__ = 'message'
    id = Column(Integer, primary_key=True)
    chat_id = orm.relationship('Chat', back_populates='message_set')
    text = Column(Text)
    owner_id = Column(Integer, ForeignKey("user.id"))
    owner = orm.relationship(User, back_populates='message_set')
    date = Column(DateTime, default=datetime.datetime.utcnow)
    image = image_attachment('UserPicture')
Esempio n. 8
0
class Question(Base):
    __tablename__ = "questions"

    id = Column(Integer, primary_key=True, index=True)
    header = Column(String, index=True)
    details = Column(String, index=True)
    creator_id = Column(Integer, ForeignKey("users.id"))
    pictures = image_attachment("QuestionPicture", uselist=True)
    creator = relationship("User", back_populates="questions")
Esempio n. 9
0
class ItemPadre(Base):
    __tablename__ = "item_padre"

    id = Column(Integer, primary_key=True)
    nombre = Column(String(50))
    marca = Column(String(50))
    foto = image_attachment('ItemPhoto')
    items = relationship('Item', backref="parent")

    def __repr__(self):
        return "ItemPadre<-%s-,'%s','%s'>" % (self.id, self.nombre, self.marca)
Esempio n. 10
0
class FoodSet(Base):
    __tablename__ = 'food_set'

    id = Column(Integer, primary_key=True)
    settype = Column(String(100))
    breakfastbool = Column(Boolean)
    picture = image_attachment('FoodImage')
    rating = Column(Integer, default=0)
    total_rater = Column(Integer, default=0)
    last_rated_at = Column(String(100), default='')
    child = relationship("FoodImage", uselist=False, back_populates="parent")
Esempio n. 11
0
class meal(Base,db.model):
    """ Contains the information about the meals prepared"""
    
    __tablename__="meal"
    meal_calories=db.Column(db.Integer, nullable=False)
    meal=db.Column(db.Integer, nullable=False)
    meal_type=db.Column(db.String(80), nullable=False)
    meal_id=db.Column(db.Integer, nullable=False, unique=True, primary_key=True)
    meal_name=db.Column(db.String(80), nullable=False)
    meal_image=image_attachment('mealPicture')
    
    def __repr__(self):
        return '<Meal for :{}>'.format(self.meal_id)
Esempio n. 12
0
class Adc(Base):
    __tablename__ = 'adc'
    name = Column(String(80), nullable=False)
    chemistry = Column(String(80), nullable=False)
    id = Column(Integer, primary_key=True)
    lot = relationship('AdcLot', cascade='all, delete-orphan')
    picture = image_attachment('AdcImg')
    user_id = Column(Integer, ForeignKey('user.id'))
    user = relationship(User)

    @property
    def serialize(self):
        return {
            'adc_id': self.id,
            'conjugation_chemistry': self.chemistry,
            'picture_url': self.picture.locate(),
            'user_id': self.user_id
        }
Esempio n. 13
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    nickname = db.Column(db.String, unique=True, nullable=False)

    avatar = entity.image_attachment('UserAvatar')
    albums = db.relationship('Album', back_populates='author')
    stories = db.relationship('Story', back_populates='author')

    @property
    def avatar_url(self) -> Optional[str]:
        with store_context(image_store):
            try:
                return self.avatar.locate()
            except IOError:
                pass
        return None

    def __repr__(self):
        return '<User: %r>' % self.nickname
Esempio n. 14
0
class User(Base):
    """User model."""

    id = Column(Integer, primary_key=True, index=True, unique=True)
    email = Column(
        EmailType,
        unique=True,
    )
    hashed_password = Column(String)
    is_active = Column(Boolean, default=False)
    _phone_number = Column(Unicode(20), unique=True)
    image = image_attachment('UserPicture')
    country_code = Column(Unicode(8))
    nickname = Column(String(30), )
    is_admin = Column(Boolean, default=False)
    created = Column(DateTime, default=datetime.datetime.utcnow)
    chat_set = orm.relationship("User_Chat", back_populates='user')
    phone_number = orm.composite(PhoneNumber, _phone_number, country_code)
    __tablename__ = "user"
Esempio n. 15
0
class AlbumEntry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    album_id = db.Column(db.Integer, db.ForeignKey('album.id'), nullable=False)
    order = db.Column(db.Integer, nullable=False)
    caption = db.Column(db.String)

    album = db.relationship('Album', back_populates='entries')
    image = entity.image_attachment('AlbumImage')

    @property
    def image_url(self) -> Optional[str]:
        with store_context(image_store):
            try:
                return self.image.locate()
            except IOError:
                pass
        return None

    def __repr__(self):
        return '<AlbumEntry: %r>' % self.caption
Esempio n. 16
0
class Cytotoxin(Base):
    __tablename__ = 'cytotoxin'
    name = Column(String(80), nullable=False)
    id = Column(Integer, primary_key=True)
    weight = Column(Float, nullable=False)
    drug_class = Column(String(80), nullable=False)
    lot = relationship('CytotoxinLot', cascade='all, delete-orphan')
    picture = image_attachment('CytotoxinImg')
    user_id = Column(Integer, ForeignKey('user.id'))
    user = relationship(User)

    @property
    def serialize(self):
        return {
            'cytotoxin_id': self.id,
            'molecular_weight': self.weight,
            'drug_class': self.drug_class,
            'picture_url': self.picture.locate(),
            'user_id': self.user_id
        }
Esempio n. 17
0
class User(Base):
    __tablename__: str = 'users'

    id = Column(Integer, primary_key=True, index=True)
    first_name = Column(String(100), nullable=True)
    last_name = Column(String(100), nullable=True)
    username = Column(String(100), nullable=False, unique=True)
    gender = Column(String(10), nullable=True)
    date_of_birth = Column(TIMESTAMP(timezone=True), nullable=True)
    email = Column(String(256), nullable=True, unique=True, index=True)
    phone_number = Column(String(15), nullable=True, unique=True)
    hashed_password = Column(String(200), nullable=False)
    # UserPicture please refer to file.mode.UserPicture
    picture = image_attachment('UserPicture')
    created_at = Column(TIMESTAMP(timezone=True), nullable=False,
                        server_default=func.now())
    updated_at = Column(TIMESTAMP(timezone=True), server_default=func.now(), nullable=False,
                        onupdate=func.now())
    active = Column(Boolean, default=False)
    number_of_followers = Column(Integer, default=text('0'))
    shop = relationship('Shop', uselist=False, back_populates='owner')
Esempio n. 18
0
class Photo(Base):
    __tablename__ = 'photo'
    __with__ = ('image_url', 'writer', 'likes_count', 'comments_count')

    id = s.Column(s.Integer, primary_key=True)
    content = s.Column(s.Text, nullable=False)

    writer_id = s.Column(s.Integer, s.ForeignKey('user.id',
                                                 ondelete='CASCADE'))
    writer = relationship('User', primaryjoin=('Photo.writer_id==User.id'))

    issue_id = s.Column(s.Integer, s.ForeignKey('issue.id',
                                                ondelete='CASCADE'))
    issue = relationship('Issue', primaryjoin='Photo.issue_id==Issue.id')

    image = image_attachment('PhotoImage')
    created_at = s.Column(s.DateTime, nullable=False, default=func.now())

    @property
    def image_url(self):
        try:
            img = self.image.find_thumbnail(width=600)
        except NoResultFound:
            img = None
        if img is None:
            if self.image.original is None:
                return None
            self.image.generate_thumbnail(width=600)
            img = self.image.find_thumbnail(width=600)
        return img.locate().split('?', 1)[0]

    @property
    def likes_count(self):
        return Like.query.filter_by(photo=self).count()

    @property
    def comments_count(self):
        return Comment.query.filter_by(photo=self).count()
Esempio n. 19
0
class Story(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    title = db.Column(db.String)
    flavour_text = db.Column(db.String)
    fulltext_html = db.Column(db.String)

    cover = entity.image_attachment('StoryCover')
    author = db.relationship('User', back_populates='stories')
    category = db.relationship('Category', back_populates='stories')

    @property
    def cover_url(self) -> Optional[str]:
        with store_context(image_store):
            try:
                return self.cover.locate()
            except IOError:
                pass
        return None

    def __repr__(self):
        return '<Story: %r>' % self.title
Esempio n. 20
0
class User(db.Model):
    """
	Initializes the User Table
	Sets up the following columns
	1. The Unique User Identifier (id)
	2. The User's username (username)
	3. The User's email (email)
	4. The user's password (password)
	5. The user's roles (roles)
	6. The user's creation data (creation)
	7. The user's bio (bio)
	"""
    id = db.Column(db.String(12), unique=True, primary_key=True)
    username = db.Column(db.String(100), unique=True, nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    roles = db.Column(db.Text)
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    bio = db.Column(db.Text)
    picture = image_attachment('ProfilePicture')

    default_role = "user"
    admin_role = "admin"
    banned_role = "banned"
    """
	To be done
	1. Setting up moderators for rooms
	2. Creating the created column

	created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
	"""
    """
	Initializes the Followers table
	Sets up the following columns
	1. The ID of the follower (follower_id)
	2. The ID of the user being followed (followed_id)
	Sets as unique
	"""

    followers = db.Table(
        'followers',
        db.Column('follower_id', db.String(12), db.ForeignKey("user.id")),
        db.Column('followed_id', db.String(12), db.ForeignKey("user.id")),
        db.UniqueConstraint('follower_id', 'followed_id', name='uix_1'))
    followed = db.relationship('User',
                               secondary=followers,
                               primaryjoin=(followers.c.follower_id == id),
                               secondaryjoin=(followers.c.followed_id == id),
                               backref=db.backref('followers', lazy='dynamic'),
                               lazy='dynamic')

    subscribed = db.relationship(
        'Room',
        secondary=Room.subscribers,
        primaryjoin=(Room.subscribers.c.subscriber_username == username),
        secondaryjoin=(Room.subscribers.c.subscribed_id == Room.id),
        backref=db.backref('subscribers', lazy='dynamic'),
        lazy='dynamic')

    def __repr__(self):
        return f'<User: {self.username}>'

    def __init__(self, username, email, roles):
        """ Used for Initializing the User"""
        self.username = username
        self.email = email
        self.roles = roles
        super(User, self).__init__()

    @property
    def rolenames(self):
        try:
            return self.roles.split(',')
        except Exception:
            return []

    @classmethod
    def lookup(cls, username):
        return cls.query.filter_by(username=username).one_or_none()

    @classmethod
    def identify(cls, id):
        return cls.query.get(id)

    @classmethod
    def is_active():
        return True

    def is_authenticated(self):
        return self.authenticated

    def set_password(self, password):
        self.password = guard.encrypt_password(password)

    def set_email(self, email):
        self.email = email

    def set_username(self, username):
        self.username = username

    def set_id(self, id):
        self.id = id

    def set_role(self, role):
        self.roles = role

    def set_bio(self, bio):
        self.bio = bio

    def check_password(self, username, password):
        return guard.authenticate(username, password)

    def get_id(self):
        return f"{self.id}"

    def follow(self, user):
        self.followed.append(user)

    def unfollow(self, user):
        self.followed.remove(user)

    def subscribe(self, room):
        self.subscribed.append(room)

    def unsubscribe(self, room):
        self.subscribed.remove(room)
Esempio n. 21
0
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(250))
    email = Column(String(250), nullable=False)
    picture = image_attachment('UserImg')
Esempio n. 22
0
class DocumentAttachment(db.Model):
    """
    An attachment for a document.

    Some attachments might not be associated with a document. This happens when a new
    document is being added and we don't yet have a document id. When the document is
    fully created the attachment ids will be included in the request and linked to the
    document.
    
    We'll clean up stranded attachments periodically.
    """
    __tablename__ = "attachments"
    log = logging.getLogger(__name__)

    id = Column(Integer, primary_key=True)

    filename = Column(String(256), nullable=False)
    mimetype = Column(String(256), nullable=False)
    document_id = Column(Integer,
                         ForeignKey('documents.id', ondelete='CASCADE'),
                         index=True)

    created_by_user_id = Column(Integer, ForeignKey('users.id'), index=True)

    created_at = Column(DateTime(timezone=True),
                        index=True,
                        unique=False,
                        nullable=False,
                        server_default=func.now())
    updated_at = Column(DateTime(timezone=True),
                        server_default=func.now(),
                        onupdate=func.current_timestamp())

    # Associations
    created_by = relationship("User", foreign_keys=[created_by_user_id])
    image = image_attachment("AttachmentImage")

    THUMBNAIL_HEIGHT = 100

    _deleted_attachments = set()

    def generate_thumbnails(self):
        self.image.generate_thumbnail(height=self.THUMBNAIL_HEIGHT)

    def set_data(self, data):
        """ Set the data for this attachment from a file-like object. """
        if self.mimetype == PDF:
            if self.id is None:
                db.session.add(self)
                db.session.flush()

            # save pdf to s3
            filename = '%d/%s' % (self.id, self.filename)
            current_store.put_file(data, 'document-attachment', filename, 0, 0,
                                   self.mimetype, False)
            data.seek(0)

            # convert to an image for use with thumbnails
            self.log.info("Converting PDF to image")
            with WandImage(file=data, resolution=300) as img:
                img.format = 'png'
                data = StringIO()
                img.save(file=data)
                data.seek(0)
            self.log.info("Converted")

        self.image.from_file(data)
        db.session.flush()
        self.generate_thumbnails()

    @property
    def thumbnail_url(self):
        return self.image.find_thumbnail(height=self.THUMBNAIL_HEIGHT).locate()

    @property
    def preview_url(self):
        return self.image.original.locate()

    @property
    def download_url(self):
        if self.mimetype == PDF:
            filename = '%d/%s' % (self.id, self.filename)
            return current_store.get_url('document-attachment', filename, 0, 0,
                                         self.mimetype)

        return self.image.original.locate()

    def size_str(self):
        return '%d,%d' % self.image.original.size

    def delete_file(self):
        if self.mimetype == PDF:
            filename = '%d/%s' % (self.id, self.filename)
            return current_store.delete_file('document-attachment', filename,
                                             0, 0, self.mimetype)

    def to_json(self):
        return {
            'id': self.id,
            'url': self.preview_url,
            'thumbnail_url': self.thumbnail_url,
            'download_url': self.download_url,
            'size': self.size_str(),
        }

    @classmethod
    def is_acceptable(cls, upload):
        """
        Is this `werkzeug.FileStorage` object a valid upload?
        """
        return upload.mimetype in MIMETYPES

    @classmethod
    def from_upload(cls, upload, user=None, document=None):
        """
        Create a new attachment from an uploaded file, a `werkzeug.FileStorage` object.
        """
        attachment = DocumentAttachment()
        attachment.document = document
        attachment.filename = secure_filename(upload.filename)
        attachment.mimetype = upload.mimetype

        if user and user.is_authenticated():
            attachment.created_by = user

        # set the data and generate thumbnails
        attachment.set_data(upload.stream)

        return attachment

    @classmethod
    def _mark_attachment_deleted(cls, mapper, connection, target):
        cls._deleted_attachments.add(target)

    @classmethod
    def _session_rollback(cls, session, previous_transaction):
        cls._deleted_attachments.clear()

    @classmethod
    def _session_commit(cls, session):
        if cls._deleted_attachments:
            for attachment in cls._deleted_attachments:
                attachment.delete_file()

            cls._deleted_attachments.clear()
Esempio n. 23
0
class User(Base):
    __tablename__ = 'user'
    __with__ = ('image_url', )
    __ex__ = ('password', )

    id = s.Column(s.Integer, primary_key=True)

    #username definitions
    _username = s.Column('username', s.String(20), nullable=False, unique=True)

    @hybrid_property
    def username(self):
        """User's unique name
        """
        return self._username

    @username.setter
    def username(self, username):
        if not username is None:
            username = username.lower()
        self._username = username

    @validates('_username')
    def _validate_username(self, key, username):
        # FIXME
        return username

    #password definitions
    _password = s.Column('password', s.String(128), nullable=True)

    @hybrid_property
    def password(self):
        """User's password
        """
        return self._password

    @password.setter
    def password(self, password):
        """Setter of :data:`password`.  It automatically hashes raw password.  

        :param password: raw password string.  
        """
        if password is None:
            self._password = None
            return
        if password == '':
            hashed = ''
        else:
            hashed = make_password(password)
        self._password = hashed

    @password.expression
    def password(self):
        return User._password

    def check_password(self, password):
        """Checks password.  

        :param password: raw password string.  
        """
        return self.password == make_password(password)

    image = image_attachment('UserImage')
    created_at = s.Column(s.DateTime, nullable=False, default=func.now())

    @property
    def image_url(self):
        if self.image.original is None:
            return None
        return self.image.locate()
Esempio n. 24
0
class User(Base):
    id = Column(Integer, primary_key=True)
    name = Column(Unicode, nullable=False)
    picture = image_attachment('UserFoodPicture')
Esempio n. 25
0
class Service(db.Model):
    """Service model"""

    id = db.Column(db.Integer, primary_key=True)
    providerName = db.Column(db.String(100), nullable=False)
    serviceHash = db.Column(db.String(100), unique=True)
    txHash = db.Column(db.String(100))
    serviceName = db.Column(db.String(100), nullable=False)
    image = image_attachment('ServiceImage')
    imageName = db.Column(db.String(30), default='default.png')
    description = db.Column(db.Text, nullable=False)
    type = db.Column(db.PickleType, nullable=False)
    features = db.Column(db.PickleType, nullable=False)
    region = db.Column(db.PickleType, nullable=False)
    deployment = db.Column(db.Text, nullable=False)
    leasingPeriod = db.Column(db.Text, nullable=False)
    price = db.Column(db.Integer, nullable=False)
    currency = db.Column(db.Text, nullable=False, default='USD')
    reviews = db.relationship('Review', backref="service", lazy='dynamic')
    __tablename__ = 'service'

    def serialize(self,
                  cosine_similarity='',
                  jaccard_similarity='',
                  euclidean_distance='',
                  manhattan_distance='',
                  pearson_correlation='',
                  minkowski_distance='',
                  weighted_similarity=[]):
        """Return object data in easily serializable format"""
        return {
            'id': self.id,
            'providerName': self.providerName,
            'serviceName': self.serviceName,
            'serviceHash': self.serviceHash,
            'txHash': self.txHash,
            'image': base64.b64encode(self.image.make_blob()).decode("utf-8"),
            'description': self.description,
            'type': self.type,
            'features': self.features,
            'region': self.region,
            'deployment': self.deployment,
            'leasingPeriod': self.leasingPeriod,
            'price': self.price,
            'currency': self.currency,
            'reviews': [r.serialize for r in self.reviews],
            'cosineSimilarity': cosine_similarity,
            'jaccardSimilarity': jaccard_similarity,
            'euclideanDistance': euclidean_distance,
            'manhattanDistance': manhattan_distance,
            'pearsonCorrelation': pearson_correlation,
            'minkowskiDistance': minkowski_distance,
            'weightedSimilarity': weighted_similarity
        }

    def json_to_obj(self, json):
        self.providerName = json["provider"]
        self.serviceName = json["productName"]
        self.description = json["description"]
        self.image = json["logo"]
        self.imageName = json["fileName"]
        self.region = json["region"]
        self.type = json["serviceType"]
        self.features = json["attackType"]
        self.deployment = json["deploymentTime"]
        self.leasingPeriod = json["leasingPeriod"]
        self.price = json["price"]
        self.txHash = json["txHash"]
        self.serviceHash = json["serviceHash"]
        return self

    def form_to_obj(self, form, file):
        self.providerName = form["provider"]
        self.serviceName = form["productName"]
        self.description = form["description"]
        self.imageName = file.filename
        self.region = form["region"].split()
        self.type = form["serviceType"].split()
        self.features = form["attackType"].split()
        self.deployment = form["deploymentTime"]
        self.leasingPeriod = form["leasingPeriod"]
        self.price = form["price"]
        self.txHash = form["txHash"]
        self.serviceHash = form["serviceHash"]
        return self

    def __repr__(self):
        return f"Service('{self.serviceName}', '{self.type}', '{self.region}', '{self.price}', '{self.currency}', '{self.txHash}', '{self.serviceHash}')"
Esempio n. 26
0
class ImageContainer(Base):
    __tablename__ = 'image_container'
    uuid = Column(UUIDType, default=uuid.uuid4, primary_key=True)
    image = image_attachment('Image')
Esempio n. 27
0
class Issue(db.Model, CRUDMixin):
    """
    Issue model class. Title and Publisher can both be referenced with
    the hidden 'publisher' and 'title' attributes

    Note: hybrid property is for sorting based on subscriber (user) number.
    # http://stackoverflow.com/questions/22876946/how-to-order-by-count-of-many-to-many-relationship-in-sqlalchemy
    """
    __tablename__ = 'issues'
    #: IDs
    id = db.Column(db.Integer, primary_key=True)
    title_id = db.Column(db.Integer, db.ForeignKey('titles.id'))
    publisher_id = db.Column(db.Integer, db.ForeignKey('publishers.id'))
    #: Attributes
    product_id = db.Column(db.String(100))
    issue_number = db.Column(db.Numeric(precision=6, scale=2))
    issues = db.Column(db.Numeric(precision=6, scale=2))
    other = db.Column(db.String(255))
    complete_title = db.Column(db.String(255))
    one_shot = db.Column(db.Boolean(), default=False)
    a_link = db.Column(db.String(255))
    thumbnail = db.Column(db.String(255))
    big_image = db.Column(db.String(255))
    retail_price = db.Column(db.Float())
    description = db.Column(db.Text())
    on_sale_date = db.Column(db.Date())
    prospective_release_date = db.Column(db.Date())
    genre = db.Column(db.String(100))
    people = db.Column(db.String(255)) #####
    popularity = db.Column(db.Float())
    last_updated = db.Column(db.DateTime())
    diamond_id = db.Column(db.String(100))
    old_diamond_id = db.Column(db.String(100))
    discount_code = db.Column(db.String(1))
    category = db.Column(db.String(100))
    upc = db.Column(db.String(100))
    #: Relationships
    cover_image = image_attachment('IssueCover')
    is_parent = db.Column(db.Boolean(), default=False)
    has_alternates = db.Column(db.Boolean(), default=False)
    @property
    def alternates(self):
        return self.query.filter(
                Issue.title==self.title,
                Issue.issue_number==self.issue_number,
                Issue.diamond_id!=self.diamond_id).all()

    @classmethod
    def popular_issues(cls, date, count=10):
        issues = cls.query.filter(
                                cls.on_sale_date==date,
                                cls.is_parent==True)\
                          .order_by(
                                cls.num_subscribers.desc(),
                                cls.complete_title.asc())\
                          .limit(count)\
                          .all()
        return issues

    @classmethod
    def featured_issue(cls, date):
        # The featured issue should always have a cover image. We check against
        # that here.
        issues = cls.popular_issues(date, count=5)
        featured_issue = None
        for issue in issues:
            if issue.cover_image.original:
                featured_issue = issue
                break
        return featured_issue

    @classmethod
    def from_raw(cls, record, sas_id='YOURUSERID'):
        # Create Issue dictionary
        i = deepcopy(record)

        # Complete Title
        try:
            complete_title = record.get('complete_title')
            # m = re.match(r'(?P<title>[^#]*[^#\s])\s*(?:#(?P<issue_number>(\d+))\s*)?(?:\(of (?P<issues>(\d+))\)\s*)?(?P<other>(.+)?)', title).groupdict()
            m = re.match(r'(?P<title>[^#]*[^#\s])\s*(?:#(?P<issue_number>([+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?))\s*)?(?:\(of (?P<issues>(\d+))\)\s*)?(?P<other>(.+)?)', complete_title).groupdict()
            i['complete_title'] = complete_title
            if m['issue_number']:
                i['issue_number'] = Decimal(m['issue_number'])
            if m['issues']:
                i['issues'] = Decimal(m['issues'])
            if m.get('other'):
                i['other'] = m['other'].strip('()')
        except (AttributeError, TypeError):
            i['complete_title'] = ''
            m = None

        # Retail Price
        try:
            retail_price = record.get('retail_price')
            i['retail_price'] = float(retail_price) if is_float(retail_price) else None
        except Exception, err:
            i['retail_price'] = 0.00

        # Affiliate Link
        try:
            a_link = record.get('a_link')
            i['a_link'] = a_link.replace('YOURUSERID', sas_id)
        except Exception, err:
            i['a_link'] = None