I started pyxley
with the goal of being able to quickly prototype
web applications in python. Inspired by Shiny, I created a handful
of widgets to enable some basic interactive data visualizations.
Rather than keep a set of highly customizable templates, I settled
upon a single, generic React component as an interface to various
components for charts, filters, etc. This provided a really flexible
framework that allowed me to focus on the data while still serving
an application that was tailored to the needs of our business partners.
However, to use pyxley
, you still had to be able to write some javascript
and navigate the React ecosystem. The latest release of pyxley
attempts
to address these issues.
If the problems listed in the github issues tab are any indication, getting
started with pyxley
is not easy. First of all, before you can get started
you need to know how to make a flask
app. There are some examples, but
it doesn't really help you understand how flask
works. So every time you
want to start a new project, you have to copy-pasta another example. If
you look at the examples you will now see __init__.py
files with
something like the following snippet.
from os import path
from pyxley.utils import create_app
from pyxley.utils import default_static_path, default_template_path
# create the flask app - provide paths to instance, static, and templates
instance_path = path.abspath(path.dirname(__file__))
app = create_app(instance_path, default_static_path(), default_template_path())
# build the layout
get_layouts(app)
if __name__ == "__main__":
app.run(debug=True)
A basic flask
app has been built into pyxley.utils.create_app
. You simply
need to provide the function with the instance path, the static folder path,
and the templates folder path. Calling app.run()
will now launch your
flask app. default_static_path
and default_template_path
point to
folders containing some basic html stuff to get you started.
Another challenge with pyxley
has been navigating the React ecosystem.
There are package managers, bundlers, ecmascript, lions, tigers, and bears.
It's so easy to mess up and spend all of your just trying to install things.
This was necessary because the previous interface to React was built on
some pretty generic templates. You could do the pyxley
stuff like
define a UILayout
and attach charts and filters, but then you had
to build a javascript bundle. If you were missing something, you ended
up with a blank screen when you ran your app.
The biggest change in this version is the removal of the build step. You
can still build a bundle and include it in your app if you want to, but
now I've included a pre-built bundle that will generate all of the
pyxley
components. This is possible because I realized that I can make
one master React component that fetches the various component props
.
In the snippet above there was a function called get_layouts
. It
could look something like the snippet below.
from pyxley import register_layouts
def get_layouts(flask_app):
# get a ui (UILayout object)
ui = make_layout()
ui.assign_routes(flask_app)
props = ui.build_props()
layouts {
"mg": {
"layout": [props], "title": "metrics-graphics"
}
}
register_layouts(layouts, flask_app)
Let's focus on the first three lines.
ui = make_layout()
ui.assign_routes(flask_app)
props = ui.build_props()
Assume the make_layout
function returns some UILayout
object.
This is the same as before, we make a UILayout
object
and then add charts and filters. In the previous version we
would call the render_layout
method to write the jsx
file
and assign the flask url rules. Instead, we now call
assign_routes
and build_props
. These methods assign the url
rules and create the props
dictionaries, respectively.
Now let's turn our attention to the layouts
dictionary and the
register_layouts
function.
layouts {
"mg": {
"layout": [props], "title": "metrics-graphics"
}
}
register_layouts(layouts, flask_app)
The layouts
dictionary provides
a basic configuration of our app. In particular, the top-level
key (mg
in this example) specifies the path of the app
(e.g. 'localhost:5000/mg'). The sub-dictionary contains a list of
props
belonging to the layout
key. This means that you can pass
a list of props from different UILayout
objects. The title
key
is used for the label in a navigation bar. The register_layouts
function will then set up a route to send the config to the client.
Admittedly, pyxley
is still light on features. However, the plotly.js
api is pretty amazing. It's flexible and it's not too much work
to set up a custom function for transmitting the data. To get started,
I've written a line_plot
function and the plotly
example demonstrates
how it all works.
Aside from the new functionality, I have only made minor tweaks to the
existing api. For the most part, if you were using pyxley
before
it should work in a similar fashion. Moving forward, I probably will
not build upon the other charting libraries because plotly is
so flexible and customizable.