From 1e6c5d4c57bfa3b1bc8349c3ac74ee2fee1862c2 Mon Sep 17 00:00:00 2001 From: "A. Jesse Jiryu Davis" Date: Sat, 2 Jan 2016 12:38:47 -0500 Subject: [PATCH] How to add a custom type with a plugin. --- content/docs/api/db/types/contents.lr | 5 +- content/docs/plugins/howto/contents.lr | 64 ++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/content/docs/api/db/types/contents.lr b/content/docs/api/db/types/contents.lr index 6753c552..a9be5ecd 100644 --- a/content/docs/api/db/types/contents.lr +++ b/content/docs/api/db/types/contents.lr @@ -5,5 +5,6 @@ summary: An overview of all the field types supported in Lektor. body: Lektor supports many different types that can be used for data modelling. -Currently it's not possible to extend these but the intention exists to make -this even more configurable from plugins in the future. + +Plugins can add additional types, see the +[plugin "how to" :ref](../../../plugins/howto/#adding-new-field-types). diff --git a/content/docs/plugins/howto/contents.lr b/content/docs/plugins/howto/contents.lr index b69eb377..ecd02ff4 100644 --- a/content/docs/plugins/howto/contents.lr +++ b/content/docs/plugins/howto/contents.lr @@ -111,3 +111,67 @@ class ExifDumpPlugin(Plugin): This dumps out the EXIF data into a JSON file and returns the artifact name. The source image is tracked as direct source for the artifact and within the function we also track the plugin's filename to rebuild if the plugin changes. + +## Adding New Field Types + +Let's say you want to add a "datetime" type to the set of +[field types :ref](../../api/db/types/) used in your models, because the +built-in "date" type has no time component. You might update `blog-post.ini` +from the [blog guide :ref](../../guides/blog) like so: + +```ini +[fields.pub_date] +label = Publication date +type = datetime # Custom "datetime" type. +``` + +In a blog post's `contents.lr`, specify its publication date like: + +``` +pub_date: 2016-01-02 12:34:56 +``` + +You can add your "datetime" type to Lektor with a plugin: + +```python +from datetime import datetime +from lektor.pluginsystem import Plugin +from lektor.types import Type + +class DatetimeType(Type): + def value_from_raw(self, raw): + return datetime.strptime(raw.value, '%Y-%m-%d %H:%M:%S') + +def strftime_filter(dt, fmt='%B %-d, %Y'): + return dt.strftime(fmt) + +class DatetimeTypePlugin(Plugin): + name = u'datetime type' + description = u'Adds a new field type, "datetime".' + + def on_setup_env(self, **extra): + self.env.types['datetime'] = DatetimeType + self.env.jinja_env.filters['strftime'] = strftime_filter +``` + +This plugin also adds a `strftime` filter to Jinja. +Render a datetime with the default format in a template like: + +```html+jinja +Published on {{ this.pub_date|strftime }} +``` + +Or a custom format: + +```html+jinja +Published on {{ this.pub_date|strftime('%Y-%m-%d') }} +``` + +Python datetime objects implement the standard comparison protocol, so +ordering still works without modifying `blog.ini`: + +```ini +[children] +model = blog-post +order_by = -pub_date, title +```