Repository: spacetelescope/jwql

Issue:
Add download button(s) to EDB web page
Users may want to download the results of their manual exploration of the EDB mnemonics. Appropriate functionality for download should be added.


Discussion:
@laurenmarietta @bourque do we already have a download button implemented in one of our pages? If not, can you point me to useful/applicable resources or examples?
This may be relevant: https://docs.djangoproject.com/en/2.1/topics/files/
We do, yes. Check out the `view_image` template/view; there are buttons there that let users download FITS/JPEG files of the image they are currently viewing.

What I anticipate will be complicated is that Django needs to be able to access the files for download. To download the FITS/JPEG image files, we added the `jwql_dir` value from the config file to the `STATICFILES_DIRS` value in `jwql_proj/settings.py`. If you want to download files from somewhere else, though, we might need to figure out a different way to facilitate that. 
Ah, the Django link you provided might be helpful with the complicated bit! I can't quite tell how their `File` object would be passed to a template to be download-able, though.
Maybe the `view_image` example is already sufficient. I am using temporary files already for the table display, so maybe it is as simple as creating a second temporary files in csv format for example and point a variable like `jpg_filepath` to it. I will give it a try.

Resolving patch:
diff --git a/jwql/website/apps/jwql/data_containers.py b/jwql/website/apps/jwql/data_containers.py
--- a/jwql/website/apps/jwql/data_containers.py
+++ b/jwql/website/apps/jwql/data_containers.py
@@ -29,7 +29,7 @@
 
 from astropy.io import fits
 from astropy.time import Time
-
+from django.conf import settings
 import numpy as np
 
 # astroquery.mast import that depends on value of auth_mast
@@ -46,6 +46,7 @@
 from jwql.instrument_monitors.miri_monitors.data_trending import dashboard as miri_dash
 from jwql.instrument_monitors.nirspec_monitors.data_trending import dashboard as nirspec_dash
 from jwql.jwql_monitors import monitor_cron_jobs
+from jwql.utils.utils import ensure_dir_exists
 from jwql.utils.constants import MONITORS, JWST_INSTRUMENT_NAMES_MIXEDCASE
 from jwql.utils.preview_image import PreviewImage
 from .forms import MnemonicSearchForm, MnemonicQueryForm, MnemonicExplorationForm
@@ -258,6 +259,30 @@ def get_edb_components(request):
                     mnemonic_query_result = get_mnemonic(mnemonic_identifier, start_time, end_time)
                     mnemonic_query_result_plot = mnemonic_query_result.bokeh_plot()
 
+                    # generate table download in web app
+                    result_table = mnemonic_query_result.data
+
+                    # save file locally to be available for download
+                    static_dir = os.path.join(settings.BASE_DIR, 'static')
+                    ensure_dir_exists(static_dir)
+                    file_name_root = 'mnemonic_query_result_table'
+                    file_for_download = '{}.csv'.format(file_name_root)
+                    path_for_download = os.path.join(static_dir, file_for_download)
+
+                    # add meta data to saved table
+                    comments = []
+                    comments.append('DMS EDB query of {}:'.format(mnemonic_identifier))
+                    for key, value in mnemonic_query_result.info.items():
+                        comments.append('{} = {}'.format(key, str(value)))
+                    result_table.meta['comments'] = comments
+                    comments.append(' ')
+                    comments.append('Start time {}'.format(start_time.isot))
+                    comments.append('End time   {}'.format(end_time.isot))
+                    comments.append('Number of rows {}'.format(len(result_table)))
+                    comments.append(' ')
+                    result_table.write(path_for_download, format='ascii.fixed_width', overwrite=True, delimiter=',', bookend=False)
+                    mnemonic_query_result.file_for_download = file_for_download
+
             # create forms for search fields not clicked
             mnemonic_name_search_form = MnemonicSearchForm(prefix='mnemonic_name_search')
             mnemonic_exploration_form = MnemonicExplorationForm(prefix='mnemonic_exploration')
@@ -281,18 +306,29 @@ def get_edb_components(request):
 
                 mnemonic_exploration_result.n_rows = len(mnemonic_exploration_result)
 
+                # generate tables for display and download in web app
                 display_table = copy.deepcopy(mnemonic_exploration_result)
+
                 # temporary html file,
                 # see http://docs.astropy.org/en/stable/_modules/astropy/table/
                 tmpdir = tempfile.mkdtemp()
-                path = os.path.join(tmpdir, 'mnemonic_exploration_result_table.html')
-                with open(path, 'w') as tmp:
+                file_name_root = 'mnemonic_exploration_result_table'
+                path_for_html = os.path.join(tmpdir, '{}.html'.format(file_name_root))
+                with open(path_for_html, 'w') as tmp:
                     display_table.write(tmp, format='jsviewer')
-                mnemonic_exploration_result.html_file = path
-                mnemonic_exploration_result.html_file_content = open(path, 'r').read()
-                # pass meta data to have access to number of mnemonics
+                mnemonic_exploration_result.html_file_content = open(path_for_html, 'r').read()
+
+                # pass on meta data to have access to total number of mnemonics
                 mnemonic_exploration_result.meta = meta
 
+                # save file locally to be available for download
+                static_dir = os.path.join(settings.BASE_DIR, 'static')
+                ensure_dir_exists(static_dir)
+                file_for_download = '{}.csv'.format(file_name_root)
+                path_for_download = os.path.join(static_dir, file_for_download)
+                display_table.write(path_for_download, format='ascii.fixed_width', overwrite=True, delimiter=',', bookend=False)
+                mnemonic_exploration_result.file_for_download = file_for_download
+
                 if mnemonic_exploration_result.n_rows == 0:
                     mnemonic_exploration_result = 'empty'
 
diff --git a/jwql/website/apps/jwql/views.py b/jwql/website/apps/jwql/views.py
--- a/jwql/website/apps/jwql/views.py
+++ b/jwql/website/apps/jwql/views.py
@@ -117,7 +117,7 @@ def nirspec_data_trending(request):
         'user': None  # Do not edit; Required for authentication
     }
 
-    #append variables to context
+    # append variables to context
     context.update(variables)
 
     # Return a HTTP response with the template and dictionary of variables


Test patch: