about summary refs log tree commit diff
path: root/wqflask/wqflask
diff options
context:
space:
mode:
authorzsloan2021-05-10 17:29:39 +0000
committerzsloan2021-05-10 17:29:39 +0000
commitc821aab3ee7b0fe42af10c2e72b6a43f9ec6f528 (patch)
tree86517882087412066d50e53288d2e70850f0eac9 /wqflask/wqflask
parent06c24f18f27daa4e32a3041878b24bea5cc30ddc (diff)
parent0dab1e85cb197ed37d93facef575f8ef934eca81 (diff)
downloadgenenetwork2-c821aab3ee7b0fe42af10c2e72b6a43f9ec6f528.tar.gz
Merge branch 'testing' of github.com:genenetwork/genenetwork2 into testing
Diffstat (limited to 'wqflask/wqflask')
-rw-r--r--wqflask/wqflask/__init__.py21
-rw-r--r--wqflask/wqflask/api/gen_menu.py251
-rw-r--r--wqflask/wqflask/api/router.py8
-rw-r--r--wqflask/wqflask/gsearch.py115
-rw-r--r--wqflask/wqflask/templates/gsearch_gene.html15
-rw-r--r--wqflask/wqflask/templates/gsearch_pheno.html15
-rw-r--r--wqflask/wqflask/views.py13
7 files changed, 272 insertions, 166 deletions
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index bf5e094b..2e94dd01 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -5,6 +5,8 @@ import jinja2
 
 from flask import g
 from flask import Flask
+from typing import Tuple
+from urllib.parse import urlparse
 from utility import formatting
 from wqflask.markdown_routes import glossary_blueprint
 from wqflask.markdown_routes import references_blueprint
@@ -16,9 +18,28 @@ from wqflask.markdown_routes import blogs_blueprint
 
 app = Flask(__name__)
 
+
+# Helper function for getting the SQL objects
+def parse_db_url(sql_uri: str) -> Tuple:
+    """Parse SQL_URI env variable from an sql URI
+    e.g. 'mysql://user:pass@host_name/db_name'
+
+    """
+    parsed_db = urlparse(sql_uri)
+    return (parsed_db.hostname, parsed_db.username,
+            parsed_db.password, parsed_db.path[1:])
+
+
 # See http://flask.pocoo.org/docs/config/#configuring-from-files
 # Note no longer use the badly named WQFLASK_OVERRIDES (nyi)
 app.config.from_envvar('GN2_SETTINGS')
+
+DB_HOST, DB_USER, DB_PASS, DB_NAME = parse_db_url(app.config.get('SQL_URI'))
+app.config["DB_HOST"] = DB_HOST
+app.config["DB_USER"] = DB_USER
+app.config["DB_PASS"] = DB_PASS
+app.config["DB_NAME"] = DB_NAME
+
 app.jinja_env.globals.update(
     undefined=jinja2.StrictUndefined,
     numify=formatting.numify)
diff --git a/wqflask/wqflask/api/gen_menu.py b/wqflask/wqflask/api/gen_menu.py
index 7f4ec1bc..0c1120ab 100644
--- a/wqflask/wqflask/api/gen_menu.py
+++ b/wqflask/wqflask/api/gen_menu.py
@@ -1,15 +1,12 @@
-from flask import g
-
-
-def gen_dropdown_json():
+def gen_dropdown_json(conn):
     """Generates and outputs (as json file) the data for the main dropdown menus on
     the home page
     """
 
-    species = get_species()
-    groups = get_groups(species)
-    types = get_types(groups)
-    datasets = get_datasets(types)
+    species = get_species(conn)
+    groups = get_groups(species, conn)
+    types = get_types(groups, conn)
+    datasets = get_datasets(types, conn)
 
     data = dict(species=species,
                 groups=groups,
@@ -19,48 +16,50 @@ def gen_dropdown_json():
     return data
 
 
-def get_species():
+def get_species(conn):
     """Build species list"""
-    results = g.db.execute(
-        "SELECT Name, MenuName FROM Species ORDER BY OrderId").fetchall()
-    return [[name, menu_name] for name, menu_name in results]
+    with conn.cursor() as cursor:
+        cursor.execute("SELECT Name, MenuName FROM Species "
+                       "ORDER BY OrderId")
+        results = cursor.fetchall()
+        return [[name, menu_name] for name, menu_name in results]
 
 
-def get_groups(species):
+def get_groups(species, conn):
     """Build groups list"""
     groups = {}
-    for species_name, _species_full_name in species:
-        groups[species_name] = []
-
-        results = g.db.execute(
-            ("SELECT InbredSet.Name, InbredSet.FullName, "
-             "IFNULL(InbredSet.Family, 'None') "
-             "FROM InbredSet, Species WHERE Species.Name = '{}' "
-             "AND InbredSet.SpeciesId = Species.Id GROUP by InbredSet.Name "
-             "ORDER BY IFNULL(InbredSet.FamilyOrder, InbredSet.FullName) "
-             "ASC, IFNULL(InbredSet.Family, InbredSet.FullName) ASC, "
-             "InbredSet.FullName ASC, InbredSet.MenuOrderId ASC")
-            .format(species_name)).fetchall()
-
-        for result in results:
-            family_name = "Family:" + str(result[2])
-            groups[species_name].append(
-                [str(result[0]), str(result[1]), family_name])
-
+    with conn.cursor() as cursor:
+        for species_name, _species_full_name in species:
+            groups[species_name] = []
+            cursor.execute(
+                ("SELECT InbredSet.Name, InbredSet.FullName, "
+                 "IFNULL(InbredSet.Family, 'None') "
+                 "FROM InbredSet, Species WHERE Species.Name = '{}' "
+                 "AND InbredSet.SpeciesId = Species.Id GROUP by "
+                 "InbredSet.Name ORDER BY IFNULL(InbredSet.FamilyOrder, "
+                 "InbredSet.FullName) ASC, IFNULL(InbredSet.Family, "
+                 "InbredSet.FullName) ASC, InbredSet.FullName ASC, "
+                 "InbredSet.MenuOrderId ASC")
+                .format(species_name))
+            results = cursor.fetchall()
+            for result in results:
+                family_name = "Family:" + str(result[2])
+                groups[species_name].append(
+                    [str(result[0]), str(result[1]), family_name])
     return groups
 
 
-def get_types(groups):
+def get_types(groups, conn):
     """Build types list"""
     types = {}
 
     for species, group_dict in list(groups.items()):
         types[species] = {}
         for group_name, _group_full_name, _family_name in group_dict:
-            if phenotypes_exist(group_name):
+            if phenotypes_exist(group_name, conn):
                 types[species][group_name] = [
                     ("Phenotypes", "Traits and Cofactors", "Phenotypes")]
-            if genotypes_exist(group_name):
+            if genotypes_exist(group_name, conn):
                 if group_name in types[species]:
                     types[species][group_name] += [
                         ("Genotypes", "DNA Markers and SNPs", "Genotypes")]
@@ -68,11 +67,11 @@ def get_types(groups):
                     types[species][group_name] = [
                         ("Genotypes", "DNA Markers and SNPs", "Genotypes")]
             if group_name in types[species]:
-                types_list = build_types(species, group_name)
+                types_list = build_types(species, group_name, conn)
                 if len(types_list) > 0:
                     types[species][group_name] += types_list
             else:
-                types_list = build_types(species, group_name)
+                types_list = build_types(species, group_name, conn)
                 if len(types_list) > 0:
                     types[species][group_name] = types_list
                 else:
@@ -83,22 +82,28 @@ def get_types(groups):
     return types
 
 
-def phenotypes_exist(group_name):
-    results = g.db.execute(
-        ("SELECT Name FROM PublishFreeze "
-         "WHERE PublishFreeze.Name = "
-         "'{}'").format(group_name + "Publish")).fetchone()
+def phenotypes_exist(group_name, conn):
+    results = []
+    with conn.cursor() as cursor:
+        cursor.execute(
+            ("SELECT Name FROM PublishFreeze "
+             "WHERE PublishFreeze.Name = "
+             "'{}'").format(group_name + "Publish"))
+        results = cursor.fetchone()
     return bool(results)
 
 
-def genotypes_exist(group_name):
-    results = g.db.execute(
-        ("SELECT Name FROM GenoFreeze " +
-         "WHERE GenoFreeze.Name = '{}'").format(group_name + "Geno")).fetchone()
-    return bool(results)
+def genotypes_exist(group_name, conn):
+    with conn.cursor() as cursor:
+        cursor.execute(
+            ("SELECT Name FROM GenoFreeze " +
+             "WHERE GenoFreeze.Name = '{}'").format(
+                 group_name + "Geno"))
+        results = cursor.fetchone()
+        return bool(results)
 
 
-def build_types(species, group):
+def build_types(species, group, conn):
     """Fetches tissues
 
     Gets the tissues with data for this species/group
@@ -116,17 +121,19 @@ def build_types(species, group):
              "ORDER BY Tissue.Name").format(species, group)
 
     results = []
-    for result in g.db.execute(query).fetchall():
-        if bool(result):
-            these_datasets = build_datasets(species, group, result[0])
-            if len(these_datasets) > 0:
-                results.append([str(result[0]), str(result[0]),
-                                "Molecular Traits"])
-
+    with conn.cursor() as cursor:
+        cursor.execute(query)
+        for result in cursor.fetchall():
+            if bool(result):
+                these_datasets = build_datasets(species,
+                                                group, result[0], conn)
+                if len(these_datasets) > 0:
+                    results.append([str(result[0]), str(result[0]),
+                                    "Molecular Traits"])
     return results
 
 
-def get_datasets(types):
+def get_datasets(types, conn):
     """Build datasets list"""
     datasets = {}
     for species, group_dict in list(types.items()):
@@ -134,83 +141,89 @@ def get_datasets(types):
         for group, type_list in list(group_dict.items()):
             datasets[species][group] = {}
             for type_name in type_list:
-                these_datasets = build_datasets(species, group, type_name[0])
+                these_datasets = build_datasets(species, group,
+                                                type_name[0], conn)
                 if bool(these_datasets):
                     datasets[species][group][type_name[0]] = these_datasets
 
     return datasets
 
 
-def build_datasets(species, group, type_name):
+def build_datasets(species, group, type_name, conn):
     """Gets dataset names from database"""
     dataset_text = dataset_value = None
     datasets = []
-    if type_name == "Phenotypes":
-        results = g.db.execute(
-            ("SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, "
-             "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, "
-             "InbredSet WHERE InbredSet.Name = '{}' AND "
-             "PublishFreeze.InbredSetId = InbredSet.Id AND "
-             "InfoFiles.InfoPageName = PublishFreeze.Name "
-             "ORDER BY PublishFreeze.CreateTime ASC").format(group)).fetchall()
-        if bool(results):
-            for result in results:
-                dataset_id = str(result[0])
-                dataset_value = str(result[1])
-                dataset_text = str(result[2])
-                if group == 'MDP':
-                    dataset_text = "Mouse Phenome Database"
-
+    with conn.cursor() as cursor:
+        if type_name == "Phenotypes":
+            cursor.execute(
+                ("SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, "
+                 "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, "
+                 "InbredSet WHERE InbredSet.Name = '{}' AND "
+                 "PublishFreeze.InbredSetId = InbredSet.Id AND "
+                 "InfoFiles.InfoPageName = PublishFreeze.Name "
+                 "ORDER BY PublishFreeze.CreateTime ASC").format(group))
+            results = cursor.fetchall()
+            if bool(results):
+                for result in results:
+                    dataset_id = str(result[0])
+                    dataset_value = str(result[1])
+                    dataset_text = str(result[2])
+                    if group == 'MDP':
+                        dataset_text = "Mouse Phenome Database"
+
+                    datasets.append([dataset_id, dataset_value, dataset_text])
+            else:
+                cursor.execute(
+                    ("SELECT PublishFreeze.Name, PublishFreeze.FullName "
+                     "FROM PublishFreeze, InbredSet "
+                     "WHERE InbredSet.Name = '{}' AND "
+                     "PublishFreeze.InbredSetId = InbredSet.Id "
+                     "ORDER BY PublishFreeze.CreateTime ASC")
+                    .format(group))
+                result = cursor.fetchone()
+                dataset_id = "None"
+                dataset_value = str(result[0])
+                dataset_text = str(result[1])
                 datasets.append([dataset_id, dataset_value, dataset_text])
-        else:
-            result = g.db.execute(
-                ("SELECT PublishFreeze.Name, PublishFreeze.FullName "
-                 "FROM PublishFreeze, InbredSet "
-                 "WHERE InbredSet.Name = '{}' AND "
-                 "PublishFreeze.InbredSetId = InbredSet.Id "
-                 "ORDER BY PublishFreeze.CreateTime ASC")
-                .format(group)).fetchone()
 
+        elif type_name == "Genotypes":
+            cursor.execute(
+                ("SELECT InfoFiles.GN_AccesionId "
+                 "FROM InfoFiles, GenoFreeze, InbredSet "
+                 "WHERE InbredSet.Name = '{}' AND "
+                 "GenoFreeze.InbredSetId = InbredSet.Id AND "
+                 "InfoFiles.InfoPageName = GenoFreeze.ShortName "
+                 "ORDER BY GenoFreeze.CreateTime "
+                 "DESC").format(group))
+            results = cursor.fetchone()
             dataset_id = "None"
-            dataset_value = str(result[0])
-            dataset_text = str(result[1])
+            if bool(results):
+                dataset_id = str(results[0])
+
+            dataset_value = "%sGeno" % group
+            dataset_text = "%s Genotypes" % group
             datasets.append([dataset_id, dataset_value, dataset_text])
 
-    elif type_name == "Genotypes":
-        results = g.db.execute(
-            ("SELECT InfoFiles.GN_AccesionId "
-             "FROM InfoFiles, GenoFreeze, InbredSet "
-             "WHERE InbredSet.Name = '{}' AND "
-             "GenoFreeze.InbredSetId = InbredSet.Id AND "
-             "InfoFiles.InfoPageName = GenoFreeze.ShortName "
-             "ORDER BY GenoFreeze.CreateTime DESC").format(group)).fetchone()
-
-        dataset_id = "None"
-        if bool(results):
-            dataset_id = str(results[0])
-
-        dataset_value = "%sGeno" % group
-        dataset_text = "%s Genotypes" % group
-        datasets.append([dataset_id, dataset_value, dataset_text])
-
-    else:  # for mRNA expression/ProbeSet
-        results = g.db.execute(
-            ("SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, "
-             "ProbeSetFreeze.FullName FROM ProbeSetFreeze, "
-             "ProbeFreeze, InbredSet, Tissue, Species WHERE "
-             "Species.Name = '{0}' AND Species.Id = "
-             "InbredSet.SpeciesId AND InbredSet.Name = '{1}' "
-             "AND ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id "
-             "AND Tissue.Name = '{2}' AND ProbeFreeze.TissueId = "
-             "Tissue.Id AND ProbeFreeze.InbredSetId = InbredSet.Id "
-             "AND ProbeSetFreeze.public > 0 "
-             "ORDER BY -ProbeSetFreeze.OrderList DESC, ProbeSetFreeze.CreateTime DESC").format(species, group, type_name)).fetchall()
-
-        datasets = []
-        for dataset_info in results:
-            this_dataset_info = []
-            for info in dataset_info:
-                this_dataset_info.append(str(info))
-            datasets.append(this_dataset_info)
+        else:  # for mRNA expression/ProbeSet
+            cursor.execute(
+                ("SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, "
+                 "ProbeSetFreeze.FullName FROM ProbeSetFreeze, "
+                 "ProbeFreeze, InbredSet, Tissue, Species WHERE "
+                 "Species.Name = '{0}' AND Species.Id = "
+                 "InbredSet.SpeciesId AND InbredSet.Name = '{1}' "
+                 "AND ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id "
+                 "AND Tissue.Name = '{2}' AND ProbeFreeze.TissueId = "
+                 "Tissue.Id AND ProbeFreeze.InbredSetId = InbredSet.Id "
+                 "AND ProbeSetFreeze.public > 0 "
+                 "ORDER BY -ProbeSetFreeze.OrderList DESC, "
+                 "ProbeSetFreeze.CreateTime "
+                 "DESC").format(species, group, type_name))
+            results = cursor.fetchall()
+            datasets = []
+            for dataset_info in results:
+                this_dataset_info = []
+                for info in dataset_info:
+                    this_dataset_info.append(str(info))
+                datasets.append(this_dataset_info)
 
     return datasets
diff --git a/wqflask/wqflask/api/router.py b/wqflask/wqflask/api/router.py
index aec74c9e..a739e5a9 100644
--- a/wqflask/wqflask/api/router.py
+++ b/wqflask/wqflask/api/router.py
@@ -6,11 +6,13 @@ import csv
 import json
 import datetime
 import requests
+import MySQLdb
 
 from zipfile import ZipFile, ZIP_DEFLATED
 
 
 import flask
+from flask import current_app
 from flask import g
 from flask import request
 from flask import make_response
@@ -845,7 +847,11 @@ def get_genotypes(group_name, file_format="csv", dataset_name=None):
 
 @app.route("/api/v_{}/gen_dropdown".format(version), methods=("GET",))
 def gen_dropdown_menu():
-    results = gen_menu.gen_dropdown_json()
+    conn = MySQLdb.Connect(db=current_app.config.get("DB_NAME"),
+                           user=current_app.config.get("DB_USER"),
+                           passwd=current_app.config.get("DB_PASS"),
+                           host=current_app.config.get("DB_HOST"))
+    results = gen_menu.gen_dropdown_json(conn)
 
     if len(results) > 0:
         return flask.jsonify(results)
diff --git a/wqflask/wqflask/gsearch.py b/wqflask/wqflask/gsearch.py
index fb8bdc55..8f66f7e9 100644
--- a/wqflask/wqflask/gsearch.py
+++ b/wqflask/wqflask/gsearch.py
@@ -121,16 +121,14 @@ class GSearch:
                             continue
 
                     max_lrs_text = "N/A"
-                    if this_trait['locus_chr'] != None and this_trait['locus_mb'] != None:
-                        max_lrs_text = "Chr" + \
-                            str(this_trait['locus_chr']) + \
-                            ": " + str(this_trait['locus_mb'])
+                    if this_trait['locus_chr'] and this_trait['locus_mb']:
+                        max_lrs_text = f"Chr{str(this_trait['locus_chr'])}: {str(this_trait['locus_mb'])}"
                     this_trait['max_lrs_text'] = max_lrs_text
 
                     trait_list.append(this_trait)
 
             self.trait_count = len(trait_list)
-            self.trait_list = json.dumps(trait_list)
+            self.trait_list = trait_list
 
             self.header_fields = ['Index',
                                   'Record',
@@ -146,6 +144,22 @@ class GSearch:
                                   'Max LRS Location',
                                   'Additive Effect']
 
+            self.header_data_names = [
+                'index',
+                'name',
+                'species',
+                'group',
+                'tissue',
+                'dataset_fullname',
+                'symbol',
+                'description',
+                'location_repr',
+                'mean',
+                'LRS_score_repr',
+                'max_lrs_text',
+                'additive',
+            ]
+
         elif self.type == "phenotype":
             search_term = self.terms
             group_clause = ""
@@ -169,24 +183,23 @@ class GSearch:
                 PublishXRef.`LRS`,
                 PublishXRef.`additive`,
                 InbredSet.`InbredSetCode`,
-                PublishXRef.`mean`
-                FROM Species,InbredSet,PublishFreeze,PublishXRef,Phenotype,Publication
-                WHERE PublishXRef.`InbredSetId`=InbredSet.`Id`
-                AND PublishFreeze.`InbredSetId`=InbredSet.`Id`
-                AND InbredSet.`SpeciesId`=Species.`Id`
+                PublishXRef.`mean`,
+                PublishFreeze.Id,
+                Geno.Chr as geno_chr,
+                Geno.Mb as geno_mb 
+                FROM Species 
+                INNER JOIN InbredSet ON InbredSet.`SpeciesId`=Species.`Id` 
+                INNER JOIN PublishFreeze ON PublishFreeze.`InbredSetId`=InbredSet.`Id` 
+                INNER JOIN PublishXRef ON PublishXRef.`InbredSetId`=InbredSet.`Id` 
+                INNER JOIN Phenotype ON PublishXRef.`PhenotypeId`=Phenotype.`Id` 
+                INNER JOIN Publication ON PublishXRef.`PublicationId`=Publication.`Id` 
+                LEFT JOIN Geno ON PublishXRef.Locus = Geno.Name AND Geno.SpeciesId = Species.Id 
+                WHERE 
+                (
+                    (MATCH (Phenotype.Post_publication_description, Phenotype.Pre_publication_description, Phenotype.Pre_publication_abbreviation, Phenotype.Post_publication_abbreviation, Phenotype.Lab_code) AGAINST ('{1}' IN BOOLEAN MODE) )
+                    OR (MATCH (Publication.Abstract, Publication.Title, Publication.Authors) AGAINST ('{1}' IN BOOLEAN MODE) )
+                )
                 {0}
-                AND PublishXRef.`PhenotypeId`=Phenotype.`Id`
-                AND PublishXRef.`PublicationId`=Publication.`Id`
-                AND	  (Phenotype.Post_publication_description REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Phenotype.Pre_publication_description REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Phenotype.Pre_publication_abbreviation REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Phenotype.Post_publication_abbreviation REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Phenotype.Lab_code REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Publication.PubMed_ID REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Publication.Abstract REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Publication.Title REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR Publication.Authors REGEXP "[[:<:]]{1}[[:>:]]"
-                    OR PublishXRef.Id REGEXP "[[:<:]]{1}[[:>:]]")
                 ORDER BY Species.`Name`, InbredSet.`Name`, PublishXRef.`Id`
                 LIMIT 6000
                 """.format(group_clause, search_term)
@@ -221,6 +234,9 @@ class GSearch:
                         this_trait['mean'] = f"{line[13]:.3f}"
                     else:
                         this_trait['mean'] = "N/A"
+                    this_trait['dataset_id'] = line[14]
+                    this_trait['locus_chr'] = line[15]
+                    this_trait['locus_mb'] = line[16]
                     this_trait['authors'] = line[7]
                     this_trait['year'] = line[8]
                     if this_trait['year'].isdigit():
@@ -241,32 +257,51 @@ class GSearch:
                     if line[11] != "" and line[11] != None:
                         this_trait['additive'] = '%.3f' % line[11]
 
+                    dataset_ob = SimpleNamespace(id=this_trait["dataset_id"], type="Publish", species=this_trait["species"])
+                    permissions = check_resource_availability(dataset_ob, this_trait['name'])
+                    if type(permissions['data']) is list:
+                        if "view" not in permissions['data']:
+                            continue
+                    else:
+                        if permissions['data'] == 'no-access':
+                            continue
+
                     this_trait['max_lrs_text'] = "N/A"
-                    trait_ob = create_trait(
-                        dataset_name=this_trait['dataset'], name=this_trait['name'], get_qtl_info=True, get_sample_info=False)
-                    if not trait_ob:
-                        continue
                     if this_trait['dataset'] == this_trait['group'] + "Publish":
                         try:
-                            if trait_ob.locus_chr != "" and trait_ob.locus_mb != "":
-                                this_trait['max_lrs_text'] = "Chr" + \
-                                    str(trait_ob.locus_chr) + \
-                                    ": " + str(trait_ob.locus_mb)
+                            if this_trait['locus_chr'] and this_trait['locus_mb']:
+                                this_trait['max_lrs_text'] = f"Chr{str(this_trait['locus_chr'])}: {str(this_trait['locus_mb'])}"
                         except:
                             this_trait['max_lrs_text'] = "N/A"
 
                     trait_list.append(this_trait)
 
             self.trait_count = len(trait_list)
-            self.trait_list = json.dumps(trait_list)
+            self.trait_list = trait_list
 
             self.header_fields = ['Index',
-                                  'Species',
-                                  'Group',
-                                  'Record',
-                                  'Description',
-                                  'Authors',
-                                  'Year',
-                                  'Max LRS',
-                                  'Max LRS Location',
-                                  'Additive Effect']
+                                'Species',
+                                'Group',
+                                'Record',
+                                'Description',
+                                'Authors',
+                                'Year',
+                                'Max LRS',
+                                'Max LRS Location',
+                                'Additive Effect']
+
+            self.header_data_names = [
+                'index',
+                'name',
+                'species',
+                'group',
+                'tissue',
+                'dataset_fullname',
+                'symbol',
+                'description',
+                'location_repr',
+                'mean',
+                'LRS_score_repr',
+                'max_lrs_text',
+                'additive',
+            ]
diff --git a/wqflask/wqflask/templates/gsearch_gene.html b/wqflask/wqflask/templates/gsearch_gene.html
index 6fd0abe8..48953d98 100644
--- a/wqflask/wqflask/templates/gsearch_gene.html
+++ b/wqflask/wqflask/templates/gsearch_gene.html
@@ -55,7 +55,15 @@
     <script language="javascript" type="text/javascript" src="/static/new/javascript/search_results.js"></script>
 
     <script type='text/javascript'>
-      var the_rows = {{ trait_list|safe }};
+      var getParams = function(url) {
+        let parser = document.createElement('a');
+        parser.href = url;
+        let params = parser.search.substring(1);
+        if(params.length > 0) {
+          return ('?'+params);
+        }
+        return params;
+      };
     </script>
 
     <script type="text/javascript" charset="utf-8">
@@ -142,7 +150,6 @@
                     $('td', row).eq(12).attr('data-export', $('td', row).eq(12).text());
                     $('td', row).eq(13).attr('data-export', $('td', row).eq(13).text());
                 },
-                'data': the_rows,
                 'columns': [
                     { 
                       'data': null,
@@ -237,11 +244,13 @@
                 'order': [[1, "asc" ]],
                 'sDom': "pitirp",
                 'autoWidth': true,
-                'iDisplayLength': 500,
                 'deferRender': false,
                 'paging': true,
                 'orderClasses': true,
                 'processing': true,
+                'iDisplayLength': 100,
+                'bServerSide': true,
+                'sAjaxSource': '/gsearch_table'+getParams(window.location.href),
                 'language': {
                   'loadingRecords': '&nbsp;',
                   'processing': 'Loading...'
diff --git a/wqflask/wqflask/templates/gsearch_pheno.html b/wqflask/wqflask/templates/gsearch_pheno.html
index 987b51a7..af9740ae 100644
--- a/wqflask/wqflask/templates/gsearch_pheno.html
+++ b/wqflask/wqflask/templates/gsearch_pheno.html
@@ -55,7 +55,15 @@
     <script language="javascript" type="text/javascript" src="/static/new/javascript/search_results.js"></script>
 
     <script type='text/javascript'>
-      var the_rows = {{ trait_list|safe }};
+      var getParams = function(url) {
+        let parser = document.createElement('a');
+        parser.href = url;
+        let params = parser.search.substring(1);
+        if(params.length > 0) {
+          return ('?'+params);
+        }
+        return params;
+      };
     </script>
 
     <script type="text/javascript" charset="utf-8">
@@ -130,7 +138,6 @@
                     $('td', row).eq(9).attr('data-export', $('td', row).eq(9).text());
                     $('td', row).eq(10).attr('data-export', $('td', row).eq(10).text());
                 },
-                'data': the_rows,
                 'columns': [
                     {
                       'data': null,
@@ -241,10 +248,12 @@
                 'sDom': "pitirp",
                 'autoWidth': false,
                 'deferRender': false,
-                'iDisplayLength': 500,
                 'paging': true,
                 'orderClasses': true,
                 'processing': true,
+                'iDisplayLength': 100,
+                'bServerSide': true,
+                'sAjaxSource': '/gsearch_table'+getParams(window.location.href),
                 'language': {
                   'loadingRecords': '&nbsp;',
                   'processing': 'Loading...'
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 276d3019..d2ede70f 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -279,6 +279,19 @@ def gsearchact():
     elif type == "phenotype":
         return render_template("gsearch_pheno.html", **result)
 
+@app.route("/gsearch_table", methods=('GET',))
+def gsearchtable():
+    logger.info(request.url)
+
+    gsearch_table_data = GSearch(request.args)
+    current_page = server_side.ServerSideTable(
+        gsearch_table_data.trait_count,
+        gsearch_table_data.trait_list,
+        gsearch_table_data.header_data_names,
+        request.args,
+    ).get_page()
+
+    return flask.jsonify(current_page)
 
 @app.route("/gsearch_updating", methods=('POST',))
 def gsearch_updating():