Ver Fonte

Add inherited SampleScan model

Unfortunately, standard flask-whooshalchemy does not support indexing inherited
models thus we have to live with that fork.
Matthias Vogelgesang há 7 anos atrás
pai
commit
bc0093c8aa

+ 54 - 0
migrations/versions/20f169ee6541_.py

@@ -0,0 +1,54 @@
+"""Add more sample fields and tables
+
+Revision ID: 20f169ee6541
+Revises: df9b39f7960f
+Create Date: 2016-09-22 09:52:59.010133
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '20f169ee6541'
+down_revision = 'df9b39f7960f'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('families',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.create_table('genuses',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.create_table('orders',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.add_column(u'samplescans', sa.Column('family_id', sa.Integer(), nullable=True))
+    op.add_column(u'samplescans', sa.Column('genus_id', sa.Integer(), nullable=True))
+    op.add_column(u'samplescans', sa.Column('order_id', sa.Integer(), nullable=True))
+    op.create_foreign_key(None, 'samplescans', 'orders', ['order_id'], ['id'])
+    op.create_foreign_key(None, 'samplescans', 'genuses', ['genus_id'], ['id'])
+    op.create_foreign_key(None, 'samplescans', 'families', ['family_id'], ['id'])
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.drop_constraint(None, 'samplescans', type_='foreignkey')
+    op.drop_constraint(None, 'samplescans', type_='foreignkey')
+    op.drop_constraint(None, 'samplescans', type_='foreignkey')
+    op.drop_column(u'samplescans', 'order_id')
+    op.drop_column(u'samplescans', 'genus_id')
+    op.drop_column(u'samplescans', 'family_id')
+    op.drop_table('orders')
+    op.drop_table('genuses')
+    op.drop_table('families')
+    ### end Alembic commands ###

+ 40 - 0
migrations/versions/df9b39f7960f_.py

@@ -0,0 +1,40 @@
+"""Start modelling dataset inheritance
+
+Revision ID: df9b39f7960f
+Revises: 1c914ed5374f
+Create Date: 2016-09-22 09:43:45.291386
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'df9b39f7960f'
+down_revision = '1c914ed5374f'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('taxons',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.create_table('samplescans',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('taxon_id', sa.Integer(), nullable=True),
+    sa.ForeignKeyConstraint(['id'], ['datasets.id'], ),
+    sa.ForeignKeyConstraint(['taxon_id'], ['taxons.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.add_column(u'datasets', sa.Column('type', sa.String(length=50), nullable=True))
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.drop_column(u'datasets', 'type')
+    op.drop_table('samplescans')
+    op.drop_table('taxons')
+    ### end Alembic commands ###

+ 7 - 1
nova/__init__.py

@@ -46,7 +46,8 @@ migrate = Migrate(app, db)
 celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
 
 
-from nova.models import User, Dataset, Access, Deletion
+from nova.models import (User, Dataset, Access, Deletion, Taxon, Order, Family,
+        Genus, SampleScan)
 
 class AdminModelView(ModelView):
     def is_accessible(self):
@@ -57,6 +58,11 @@ admin.add_view(AdminModelView(User, db.session))
 admin.add_view(AdminModelView(Dataset, db.session))
 admin.add_view(AdminModelView(Access, db.session))
 admin.add_view(AdminModelView(Deletion, db.session))
+admin.add_view(AdminModelView(Taxon, db.session))
+admin.add_view(AdminModelView(Order, db.session))
+admin.add_view(AdminModelView(Family, db.session))
+admin.add_view(AdminModelView(Genus, db.session))
+admin.add_view(AdminModelView(SampleScan, db.session))
 
 
 from nova.resources import Datasets, Dataset

+ 75 - 3
nova/models.py

@@ -1,7 +1,7 @@
 import os
 import datetime
 import hashlib
-import flask_whooshalchemy
+import flask_whooshalchemyplus
 from nova import app, db
 from sqlalchemy_utils import PasswordType, force_auto_coercion
 from itsdangerous import Signer, BadSignature
@@ -78,6 +78,8 @@ class Dataset(db.Model):
     __searchable__ = ['name']
 
     id = db.Column(db.Integer, primary_key=True)
+    type = db.Column(db.String(50))
+
     name = db.Column(db.String)
     description = db.Column(db.String)
     path = db.Column(db.String)
@@ -88,6 +90,11 @@ class Dataset(db.Model):
     parent = db.relationship('Dataset')
     accesses = db.relationship('Access', cascade='all, delete, delete-orphan')
 
+    __mapper_args__ = {
+        'polymorphic_identity': 'dataset',
+        'polymorphic_on': type
+    }
+
     def to_dict(self):
         path = os.path.join(app.config['NOVA_ROOT_PATH'], self.path)
         return dict(name=self.name, path=path, closed=self.closed)
@@ -96,6 +103,71 @@ class Dataset(db.Model):
         return '<Dataset(name={}, path={}>'.format(self.name, self.path)
 
 
+class Taxon(db.Model):
+
+    __tablename__ = 'taxons'
+
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String)
+
+    def __repr__(self):
+        return '<Taxon(name={}>'.format(self.name)
+
+
+class Order(db.Model):
+
+    __tablename__ = 'orders'
+
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String)
+
+    def __repr__(self):
+        return '<Order(name={}>'.format(self.name)
+
+
+class Family(db.Model):
+
+    __tablename__ = 'families'
+
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String)
+
+    def __repr__(self):
+        return '<Family(name={}>'.format(self.name)
+
+
+class Genus(db.Model):
+
+    __tablename__ = 'genuses'
+
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String)
+
+    def __repr__(self):
+        return '<Genus(name={}>'.format(self.name)
+
+
+class SampleScan(Dataset):
+
+    __tablename__ = 'samplescans'
+
+    __mapper_args__ = {
+        'polymorphic_identity': 'samplescan'
+    }
+
+    id = db.Column(db.Integer, db.ForeignKey('datasets.id'), primary_key=True)
+
+    taxon_id = db.Column(db.Integer, db.ForeignKey('taxons.id'), nullable=True)
+    genus_id = db.Column(db.Integer, db.ForeignKey('genuses.id'), nullable=True)
+    family_id = db.Column(db.Integer, db.ForeignKey('families.id'), nullable=True)
+    order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=True)
+
+    taxon = db.relationship('Taxon')
+    genus = db.relationship('Genus')
+    family = db.relationship('Family')
+    order = db.relationship('Order')
+
+
 class Access(db.Model):
 
     __tablename__ = 'accesses'
@@ -129,5 +201,5 @@ class Deletion(db.Model):
         return '<Deletion(user={}, dataset={})>'.format(self.user.name, self.dataset_name)
 
 
-flask_whooshalchemy.whoosh_index(app, Dataset)
-flask_whooshalchemy.whoosh_index(app, User)
+flask_whooshalchemyplus.whoosh_index(app, Dataset)
+flask_whooshalchemyplus.whoosh_index(app, User)

+ 1 - 1
nova/views.py

@@ -3,7 +3,7 @@ import io
 import re
 from functools import wraps
 from nova import app, db, login_manager, fs, logic, memtar, tasks
-from nova.models import User, Dataset, Access, Deletion
+from nova.models import User, Dataset, SampleScan, Access, Deletion
 from flask import (Response, render_template, request, flash, redirect,
                    url_for, jsonify)
 from flask_login import login_user, logout_user, current_user

+ 1 - 1
requirements.txt

@@ -7,7 +7,7 @@ Flask-Migrate
 Flask-SQLAlchemy
 Flask-WTF
 flask-restful
-flask_whooshalchemy
+flask_whooshalchemyplus
 SQLAlchemy-Utils
 Sphinx
 passlib