{ "info": { "author": "Alessandro Molina", "author_email": "alessandro.molina@axant.it", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: TurboGears", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "About Data Helpers\n-------------------------\n\n.. image:: https://drone.io/bitbucket.org/axant/tgext.datahelpers/status.png\n :target: https://drone.io/bitbucket.org/axant/tgext.datahelpers\n\ntgext.datahelpers is a collection of utilities to help manage stored data\nin common web applications.\n\ntgext.datahelpers contains:\n\n- Validators to fetch objects from database by Id (both SQLA and Ming)\n- Store Attachments by just declaring a Column in your model\n- Store image and thumbnails by just declaring a Column in your model\n\nInstalling\n-------------------------------\n\ntgext.datahelpers can be installed both from pypi or from bitbucket::\n\n easy_install tgext.datahelpers\n\nshould just work for most of the users\n\nValidators\n--------------------------------\n\n``tgext.datahelpers.validators`` provides the ``SQLAEntityConverter`` and\n``MingEntityConverter`` that convert the given\nparameter (which is expected to be the primary key of an object) to\nthe actually object itself::\n\n from tgext.datahelpers.validators import SQLAEntityConverter\n\n @expose()\n @validate({'doc':SQLAEntityConverter(Document)}, error_handler=index)\n def photo(self, doc):\n return redirect(doc.photo.url)\n\nValidators module provides also the ``validated_handler`` utility which\nmakes possible to apply validation also to error_handlers.\nNormally TurboGears would execute @validate based validation only when\nthe controller method is called through a request, when you use a controller\nmethod as the error_handler of another method the error_handler @validate\ngets skipped and arguments are passed as they are.\n\nUsing ``validated_handler`` it is possible to change this behavior and\napply validation even to error_handlers::\n\n from tgext.datahelpers.validators import SQLAEntityConverter, validated_handler\n\n @expose()\n @validate({'doc':validators.Int(not_empty=True)},\n error_handler=index)\n def next(self, doc):\n return dict(doc=doc+1)\n\n @expose()\n @validate({'doc':SQLAEntityConverter(Document)},\n error_handler=validated_handler(next))\n def photo(self, doc):\n return redirect(doc.photo.url)\n\nIn the previous example when calling /photo/3 if document 3 is not available\nit would be retrieved the successive document by calling next. If validated_handler\ngets removed from photo @validate you would get an error as doc wouldn't be an integer.\n\nUtilities\n-----------------------------------\n\n``tgext.datahelpers.utils`` provides the ``slugify`` function to\ngenerate slug urls for entities which are meaningful for users.\n\nThe generated slugs includes the entity id so that it can identify\nunique elements making possible for EntityConverter validators\nto support retrieving objects from the generated slug. Add\n``slugified=True`` option to the entity converted to load\nback an entity by its slug.\n\nSample usage::\n\n >>> from tgext.datahelpers.utils import slugify\n\n >>> entity = DBSession.query(Entity).get(5)\n >>> url = slugify(entity, entity.name)\n >>> print url\n 'this-is-a-very-long-phrase-5'\n\nUtility functions also provide a ``fail_with`` object which\ncan be used with turbogears @validate error_handler to report\na missing element or forbidden access::\n\n from tgext.datahelpers.validators import SQLAEntityConverter\n from tgext.datahelpers.utils import fail_with\n\n @expose()\n @validate({'doc':SQLAEntityConverter(Document, slugified=True)},\n error_handler=fail_with(404))\n def photo(self, doc):\n return redirect(doc.photo.url)\n\nEntities Based Caching\n-----------------------------------\n\n``tgext.datahelpers.caching`` provides the ``@entitycached`` decorator\nwhich can be used to cache methods (and helpers) based on a parameter\nwhich is a Ming or SQLAlchemy entity.\n\nWhenever the entity gets updated the cache is invalidated and the method\ncalled again, otherwise calling the method will return the value from the cache.\n\nTo determine if the entity has changed it will try to retrieve the\n``cache_key`` property of the entity, if not available a cache key\nwill be automatically generated using the primary key and ``updated_at``\nproperty of the entity.\n\nSample usage::\n\n from tgext.datahelpers.caching import entitycached\n\n @entitycached('post')\n def render_post(post):\n return '