Dynamic Helpers

posted 2016-10-26 by Herb

DataZoomer apps can now define their own helpers on the fly. Simply define your helper by placing a callable in the system.helpers dict and then you can use it in content, like this:

from zoom import system, page

def setup():
    system.helpers['upper'] = unicode.upper

def app(request):
    setup()
    content = """
       This should be in <dz:upper "upper case">
    """
    return page(content, title='Helper Test')

That's it.

Introducing Components

posted 2016-09-18 by Herb

Pages on a web site are often compositions of many smaller pieces which we call components. These components are assembled together, sometimes along with some content and theme to form an entire page. Components which used to be mostly static page elements are increasingly becoming dynamic and often make use of CSS and JavaScript and associated libraries. Assembling all of these components together into a page so that everything ends up in the right place can be messy.

To make this simpler DataZoomer, DataZoomer can take care of these details for you. To create a page element, you simply need to pass the various parts of the component to the component function and DataZoomer will make sure the various parts get to the right place.

Example:

def app():
    msg = 'Are you sure you want to delete {}?'
    content = msg.format(record.name)
    button = '<button onclick="reallySure()">Delete</button>
    js = """
        function reallySure() {
            alert("I am an alert box!");
        }
    """
    css = """
        button { color: red; }
    """
    content = component(button, js=js, css=css)
    return page(content, title='Delete Record')

This is designed to be very similar to the way entire pages are created using the page function, and in fact it handles many of the same parameters. Those are:

  • js - JavaScript code you want to include
  • libs - URLs to JavaScript libraries you want to include
  • css - CSS
  • styles - URLs to CSS style sheets you want to bring in
  • head - anything you want placed into the head of the page
  • tail - anything you want placed at the end of the page

In the future we're going to add support for additional types, such as LESS, HAML, Coffee, etc..

Drag and Drop Images

posted 2015-12-28 by Herb

A new ImagesField has been added to the fields module that allows you to add images fields to models by simply including the field in a form. This new field type offers drag and drop image uploading using the awesome dropzone.js module.

In addition, the collect module has been updated to provide support for the ImagesField so if you are using the collect module as the basis for your app, it supplies the necessary methods to support the ImagesField. This is a good place to look if you are using custom controllers or views in your app and need to provide support for ImagesField on your own.

Here's an example of a model for a simple photo gallery app with multiple photo albums.

from zoom.fields import TextField, ImagesField
from zoom.collect import Collection

class PhotoAlbum(CollectionRecord): pass

album_fields = Form(
    TextField('Album Name'),
    ImagesField('Photos'),
)

app = Collection('Albums', album_fields, PhotoAlbum)

The images are stored as files and are linked to the current record via an attachment model. Currently the field supports uploading of png, jpg and gif only.

Simpler Collections

posted 2015-05-31 by Herb

The collect module has been updated to make creating collections even simpler than before. With this change you now just have to give the collection a name, define the fields you want to use in your collection and define the model want the collection stored with. Then with one line of code you can create the collection.

Example:

file: app.py

from zoom import collect
from zoom.fields import *

class ItemsItem(Record): pass

Item = ItemsItem

item_fields = Fields(
    TextField('Name'),
    MemoField('Description'),
    NumberField('Price'),
    ImageField('Photo'),
    )

app = Collection('Item', item_fields, Item, url='/mynewapp')

That's it.

Caching

posted 2014-11-13 by Herb

An experimental caching module has been added. This module makes it really simple to add caching to any method or function that returns a string (i.e. page content) using decorators.

example:

    >>> class foo(object):
    ...
    ...     def __init__(self, value):
    ...         self.value = value
    ...
    ...     @cached(key)
    ...     def get_value(self, param=''):
    ...         return self.value + param
    ...
    >>> a = foo('bar')
    >>> a.get_value()
    'bar'
    >>> a.value = 'bahr'
    >>> a.get_value()
    'bar'

This is still experimental so the API may change. Feedback welcome.

Enhanced Logging

posted 2014-11-12 by Herb

We've added a ton of new logging features that allow the usual system level logging but also user activity logging which can be used in dashboards and progress reports.

The collect module has been outfitted with this new logging capability so any apps written using it will now have logging built in. Of course developers can add whatever additional activity logging makes sense for their application.

Chosen

posted 2014-10-28 by Herb

We've added support for the selection widget chosen built by Harvest. See it in action on the sample page.

Added system.users

posted 2014-07-31 by Herb

The users table is now automatically loaded at runtime and placed conveniently in the system module. The system.users object is an instance of UserStore which is a subclass of RecordStore.

New db Instance

posted 2014-06-26 by Herb

The system object now has a db instance called system.db which is automatically initialized to connect to the system database specified in the config file (the same one that system.database uses).

New DataZoomer db Module

posted 2014-06-23 by Herb

The new db is now implemented in DataZoomer on an experimental basis. The db module is much lighter weight and faster than the current database module.

It achieves this by doing the minimum required to provide a useful database API and by making use of generators and fetchmany instead of fetchall as is done in the database module.

The db module will be most useful when dealing with very large databases or in instances when every bit of speed matters.

Additional modules are being developed to use the db module to provide high level functionality such as record and sparse key value storage.

This db new module will eventually replace the database module entirely.

Welcome!

posted 2014-05-16 by Herb

DataZoomer is an open source dynamic web framework for Python that makes modern web development easier. This blog is where we'll be posting information about development progress.

DataZoomer source code is hosted on GitHub and is supported by Dynamic Solutions.