Gramex 1.66 lets you auto-create table schema, fetch inserted rows, cache queries, auto-compile SASS files, add pre-defined themes, restrict HTTP methods on any handler, Git LFS support, and more.
FormHandler POST automatically creates a table (if required) when inserting a row. But the table structure may not be what you intended.
For example, if the first user POSTs:
?password=123
, the password column becomes an integer, not string?age=
, the age column becomes a string, not an integerUse Columns:
to define column type when creating
tables. For example:
handler: FormHandler
kwargs:
url: "postgresql://$USER:$PASS@server/db" # Pick any database
table: profile # Pick any table name to create
id: id # The "id" column is primary key
# Define your table's columns
columns:
user: TEXT # Use any SQL type allowed by DB
password: VARCHAR(40) # including customizations
age:
type: INTEGER # You can also specify as a dict
nullable: true # Allows NULL values for this field
default: 0 # that default to zero
id:
type: INTEGER # Define an integer ID column
primary_key: true # as a primary key
autoincrement: true # that auto-increments
If the profile
table already has any of these columns, it is left unaltered. Else, the missing
columns are added. No columns are removed.
When a user inserts a row using FormHandler POST, it’s useful to show details about the row added. For example, if the user submits an employee record, it’s useful to link to the new record added.
The JSON object returned by FormHandler POST now has an
array of inserted IDs. For example, in the auto-created table above,
the user POSTS ?user=alpha&password=alpha
, the response would look like:
{
"data": {
"filters": [],
"ignored": [],
"inserted": [
{
"id": 1
}
]
}
}
"inserted": [...]
has the list of records inserted, with the primary keys’ values populated in
each record.
Note: This works only if one record is inserted in the current release. Future releases will support fetching IDs for multiple inserts.
If a FormHandler query is slow, you can cache it using a fast-to-test condition.
For example:
FormHandler supports a state:
kwarg that can be set as any Python
expression. This is evaluated every time the FormHandler is accessed. If the returned value
changes, the query is run. Else, the previously cached query value is returned.
For example:
kwargs:
query: ... # Some long-running query
# Use any ONE such state: in your gramex.yaml
# 1. Re-run query once per day
state: datetime.date.today() # Run once per day
# OR: 2. Re-run when the number of records in `table` changes
state: "gramex.data.filter(
'sqlite:///my.db',
query='SELECT COUNT(*) FROM table')"
# OR: 3. Re-run when the latest `date` in `table` changes
state: "gramex.data.filter(
'sqlite:///my.db',
query='SELECT MAX(date) FROM table')"
# OR: 4. Re-run when any utils.cache_func()'s result changes
state: utils.cache_func(args, handler)
SASS is a superset of CSS that supports variables, color and size operators, nested rules, custom functions, and more. It makes writing CSS faster and easier.
FileHandler now auto-compiles SASS files. Any .scss
file is compiled
into CSS using node-sass. To enable this in your
FileHandler, just add:
kwargs:
sass: "*.scss, *.sass"
If you haven’t created your own FileHandler, the default FileHandler automatically compiles SASS.
Any URL query parameters are automatically passed to your SASS file as variables. For example,
color.scss?color=red is the same as adding $color: red;
before your color.scss
.
This release adds a number of pre-defined Bootstrap themes from Bootswatch and Bootstrap Themes Guide. Browse these at /ui/theme/. You can link to these directly. For example:
Or, you can import them in your style.scss
. For example:
// Include any one of these lines to import the theme
@import "theme/default";
@import "theme/bootswatch/slate";
@import "theme/themes-guide/fesca";
Gramex UI components are available as pure SASS files that you can import in your stye.scss
. For
example, your style.scss
can include:
// Add any Bootstrap variables here. For example:
$dark: #204066;
// Import the Gramex UI components, which include Bootstrap
@import "gramexui";
// Add your custom CSS/SCSS code that overrides Bootstrap / Gramex UI components
.component {
border: 1px solid $dark;
}
FileHandler transforms now lets you pick multiple
extensions for the same transform. For example, to treat all template*.html
and template*.svg
files as templates, use:
kwargs:
template: "template*.html, template*.svg"
This is useful when you want to render files normally, except certain files that are templates.
Similarly, to treat all *.scss
and *.sass
files as SASS files, use:
kwargs:
sass: "*.scss, *.sass"
File patterns can be joined one or more spaces and/or commas.
This can also be used in FileHandler under kwargs.transform:
like this:
kwargs:
transform:
"*.md, *.markdown": # Convert .md and .markdown files
function: markdown.markdown(content)
Some handlers support multiple HTTP methods. For example, you can send a GET or a POST request to a FileHandler, FunctionHandler, or FormHandler.
To allow only specific HTTP methods (e.g. to disable PUT/DELETE for a FileHandler), use:
kwargs:
# Use any one of these lines
methods: GET # Only allows the GET method
methods: GET, POST # Only allow GET/POST, not PUT, DELETE, etc
methods: [GET, POST] # Same as above
methods: GET, POST, PUT, DELETE, OPTIONS, PATCH # Allow all methods
This works for all handlers. If the user requests a non-allowed method, or the underlying
handler does not support it, Gramex raises a HTTP 405: Method not allowed
response.
Git LFS stores large files in Git repos without slowing or bloating the repo.
If Git LFS is installed on your system when you run gramex init
, it will
automatically track all files under assets/**
via Git LFS.
Earlier, these files were in .gitignore
. If your system does not have Git LFS, they will continue
to be in .gitignore
.
gramex init
automatically creates a style.scss
instead of style.css
. SCSS is encouraged.
It also uses the default theme via @import "theme/default"
.X-XSS-Protection: 1; mode=block
HTTP header. (Earlier, it just set X-XSS-Protection: 1;
without the mode=block
, which is less secure.)handler
. If it does, it passes the current
handler object.gramex.config.slug.filename()
and
gramex.config.slug.module()
. These convert user-provided strings into valid filenames and
modules more reliably.=
in them.
Fixed by Mohammed Niyas and Naveen ManukondaNone
.
This happens when using a modify
to render custom output, for example.
Now, Gramex does not raise this warning.Gramex 1.67 will be released on 1 Dec and will feature:
MLHandler
class that makes it easy to create and deploy machine learning models. This
will include scikit-learn, Keras and PyTorch models. This will deprecate
ModelHandler.4 of the features promised in this release are delayed. 2 will be released in December.
MLHandler
.2 are deferred to a future release.
The Gramex code base has:
=
in them=
in themSee the Gramex installation and upgrade instructions.
NOTE: The 1.66 Conda package has an installation issue. Use Docker or PyPi.
Note: Gramex 1.66 does not work with Python 3.8. We recommend Python 3.7.