On Tue, May 30, 2017 at 05:25:06PM +1000, Dan Callaghan wrote:

Hi Dan,

This is V2 of my patch.  Things move farther along.  But now I can't
actually 'send_file'.  It doesn't return anything.  There is data added to
the temp file and the function returns a flask response. Do I have to
convert the flask response to a cherrypy one or something here?

Let me inline my issues in the patch.

Cheers,
Don


diff --git a/Server/assets/csv-export.js b/Server/assets/csv-export.js
new file mode 100644
index 0000000..09a3517
--- /dev/null
+++ b/Server/assets/csv-export.js
@@ -0,0 +1,43 @@
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+;(function () {
+
+var CSVExportSelection = Backbone.Model.extend({
+});
+
+window.CSVExport = Backbone.View.extend({
+    template: JST['csv-export'],
+    events: {
+        'submit form': 'submit',
+        'change .csv-fields input': 'update_selection',
+    },
+    initialize: function (options) {
+        this.csv_types = options.options['csv_types']
+        this.selection = new CSVExportSelection({
+            csv_type: this.csv_types[0]
+        });
+        this.render();
+    },
+    render: function () {
+        this.$el.html(this.template(this));
+    },
+    update_selection: function (evt) {
+        var elem = evt.currentTarget;
+        this.selection.set(elem.name, $(elem).val());
+    },
+    submit: function (evt) {
+        evt.preventDefault();
+        var xhr = $.ajax({
+            url: 'csv/action_export',
+            type: 'POST',
+            data: this.selection.attributes,
+            traditional: true,
+        });
+    },
+});
+
+})();
diff --git a/Server/assets/jst/csv-export.html 
b/Server/assets/jst/csv-export.html
new file mode 100644
index 0000000..2fd0366
--- /dev/null
+++ b/Server/assets/jst/csv-export.html
@@ -0,0 +1,20 @@
+<form class="form-horizontal">
+  <fieldset class="csv-fields">
+    <div class="control-group">
+      <label class="control-label">CSV Type</label>
+      <div class="controls">
+        <% _.each(csv_types, function (csv) { %>
+          <label class="radio">
+            <input type="radio" name="csv_type" value="<%- csv.toLowerCase() 
%>"
+              <% if (csv == 'system' ) { %>checked<% } %>
+            />
+            <%- csv %>
+          </label>
+        <% }) %>
+      </div>
+    </div>
+    <div class="form-actions">
+      <button class="btn btn-primary" type="submit">Export CSV</button>
+    </div>
+  </fieldset>
+</form>
diff --git a/Server/bkr/server/CSV_import_export.py 
b/Server/bkr/server/CSV_import_export.py
index 41fcb26..24ad6e2 100644
--- a/Server/bkr/server/CSV_import_export.py
+++ b/Server/bkr/server/CSV_import_export.py
@@ -10,7 +10,11 @@
 from bkr.server import identity
 from bkr.server.xmlrpccontroller import RPCRoot
 from tempfile import NamedTemporaryFile
-from cherrypy.lib.cptools import serve_file
+#from cherrypy.lib.cptools import serve_file
+from flask import send_file, request
+from bkr.server.flask_util import render_tg_template, auth_required, 
admin_auth_required
+
+from bkr.server.app import app
 from bkr.server.model import (System, SystemType, Activity, SystemActivity,
                               User, Group, LabController, LabInfo,
                               OSMajor, OSVersion,
@@ -70,6 +74,52 @@ def line_num(self):
     def fieldnames(self):
         return self.reader.fieldnames
 
+# For XMLRPC methods in this class.
+exposed = False
+
+export_help_text = XML(u'<span>Refer to the <a 
href="http://beaker-project.org/docs/'
+                       'admin-guide/interface.html#export" target="_blank">'
+                       'documentation</a> to learn more about the exported 
data.</span>').expand()
+import_help_text = XML(u'<span>Refer to the <a 
href="http://beaker-project.org/docs/'
+                       'admin-guide/interface.html#import" target="_blank">'
+                       'documentation</a> for details about the supported CSV 
format.</span>').expand()
+

Not sure how to add these correctly.  Through the 'options' in the
render_tg_template call?


+@app.route('/csv', methods=['GET'])
+@auth_required
+def index():
+    options = {}
+    options['csv_types'] = ('system', 'system_id', 'labinfo', 'power',
+                            'exclude', 'install', 'keyvalue', 'system_pool',
+                            'user_group')

I need to create a better map here, ie   options['csv_types'] = { 'system':
'System', ...}???


+    #return render_template('assets.jst.csv_export.html', options=options)
+    return render_tg_template('bkr.server.templates.csv_export', {
+        'title' : u'CSV Export Don',
+        'options' : options
+    })

I tried to use the 'backgrid' template here, but it came falling because I
didn't define a 'grid_collection_type'.  I don't think I need that and
couldn't figure out the javascript to 'if undefined skip..' logic.

So instead I use a new csv_export.kid file.


+
+@app.route('/csv/action_export', methods=['POST'])
+@auth_required
+def action_export():
+    log = []
+    csv_type = request.form.get('csv_type')
+
+
+    file = NamedTemporaryFile()
+    logger.debug("DON: request: %s, file %s" % (csv_type, file.name))
+    if csv_type in csv_types:
+        csv_types[csv_type]._to_csv(file)
+    else:
+        log.append("Invalid csv_type %s" % csv_type)
+    file.seek(0)
+
+    logger.debug('DON CSV export :  %s', file)
+    filename = "%s.csv" % csv_type
+    ret = send_file(file.name, mimetype="text/csv",
+                                 as_attachment=True,
+                                 attachment_filename=filename)

This returns a flask response.  Not sure if it is valid, it barfs with I try
to print it.  Regardless, nothing happens as a result, no pop up download
window, no failure, nothing.  The csv_type data is right though.


That's it for issues...

+
+    return ret
+
 class CSV(RPCRoot):
     # For XMLRPC methods in this class.
     exposed = False
@@ -110,8 +160,6 @@ class CSV(RPCRoot):
         submit_text = _(u'Export CSV'),
     )
 
-    @expose(template='bkr.server.templates.form')
-    @identity.require(identity.not_anonymous())
     def index(self, **kw):
         return dict(
             form = self.exportform,
@@ -121,8 +169,6 @@ def index(self, **kw):
             value = kw,
         )
 
-    @expose(template='bkr.server.templates.form-post')
-    @identity.require(identity.in_group('admin'))
     def csv_import(self, **kw):
         return dict(
             form = self.importform,
@@ -132,13 +178,12 @@ def csv_import(self, **kw):
             value = kw,
         )
 
-    @expose()
-    @identity.require(identity.not_anonymous())
     def action_export(self, csv_type, *args, **kw):
         file = NamedTemporaryFile()
         log = self.to_csv(file, csv_type)
         file.seek(0)
 
+        logger.debug('DON CSV export with send_file type: %s', csv_type)
         return serve_file(file.name, contentType="text/csv",
                                      disposition="attachment",
                                      name="%s.csv" % csv_type)
@@ -181,8 +226,6 @@ def _import_row(self, data, log):
             raise ValueError('Invalid csv_type %s or missing required fields'
                     % data['csv_type'])
 
-    @expose(template='bkr.server.templates.csv_import')
-    @identity.require(identity.in_group('admin'))
     def action_import(self, csv_file, *args, **kw):
         """
         TurboGears method to import data from csv
@@ -247,9 +290,11 @@ def _to_csv(cls, file):
         header = csv.writer(file)
         header.writerow(['csv_type'] + cls.csv_keys)
         writer = csv.DictWriter(file, ['csv_type'] + cls.csv_keys)
+        logger.debug("DON: %s" % cls.csv_keys)
         for item in cls.query():
             for data in cls.to_datastruct(item):
                 data['csv_type'] = cls.csv_type
+                logger.debug("DON: data is %s" % data)
                 # XXX remove encoding in Python 3...
                 writer.writerow(dict((k, unicode(v).encode('utf8')) for k, v 
in data.iteritems()))
 
diff --git a/Server/bkr/server/assets.py b/Server/bkr/server/assets.py
index 0c5a117..71747f4 100644
--- a/Server/bkr/server/assets.py
+++ b/Server/bkr/server/assets.py
@@ -90,6 +90,7 @@ def _create_env(source_dir, output_dir, **kwargs):
             'pools.js',
             'query-builder.js',
             'reserve-workflow.js',
+            'csv-export.js',
             'installation-model.js',
             'task-library-model.js',
             'scheduler-model.js',
diff --git a/Server/bkr/server/controllers.py b/Server/bkr/server/controllers.py
index cece8db..936cdc2 100644
--- a/Server/bkr/server/controllers.py
+++ b/Server/bkr/server/controllers.py
@@ -146,7 +146,7 @@ class Root(RPCRoot):
     users = Users()
     arches = Arches()
     auth = Auth()
-    csv = CSV()
+    #csv = CSV()
     jobs = Jobs()
     recipesets = RecipeSets()
     recipes = Recipes()
diff --git a/Server/bkr/server/templates/csv_export.kid 
b/Server/bkr/server/templates/csv_export.kid
new file mode 100644
index 0000000..16f7487
--- /dev/null
+++ b/Server/bkr/server/templates/csv_export.kid
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"; xmlns:py="http://purl.org/kid/ns#";
+    py:extends="'master.kid'">
+<head>
+<title>$title</title>
+</head>
+<body>
+<div class="page-header">
+  <h1>$title</h1>
+</div>
+<div class="csv_export"></div>
+<script type="text/javascript">
+$(function () {
+    new CSVExport({
+        el: '.csv_export',
+        options: ${tg.to_json(options)},
+    });
+});
+</script>
+</body>
+</html>
_______________________________________________
Beaker-devel mailing list -- beaker-devel@lists.fedorahosted.org
To unsubscribe send an email to beaker-devel-le...@lists.fedorahosted.org

Reply via email to