Package: django-amber
# Django Amber[![Build Status](https://travis-ci.org/inglesp/django-amber.svg?branch=master)](https://travis-ci.org/inglesp/django-amber)Harness the power of Django to build your static sites!## StatusAlpha-ish.  Django Amber is not yet used in production anywhere.## InstallationInstall Django Amber with `pip`:pip install django-amber## Usage### The basic ideaDjango Amber is a static site generator, in the mould of[Jekyll](https://jekyllrb.com/) or [Pelican](http://docs.getpelican.com/)With Django Amber, you build your website using Django, making use of the fullDjango toolkit: models, views, urlconfs, templates, tests, and so on.  DjangoAmber then provides a way to dump the dynamically generated contents of yoursite to a tree of static files on the filesystem, so that they can be served byyour favourite webserver or static site host.Additionally, instead of storing your data in a database, your data isserialized to files on the filesystem.  This means that you can keep your dataunder version control, and benefit from all the tooling which that brings.Each model instance is serialized to its own file.  Serialization is documentedunder "Models" below.### Management commandsDjango Amber provides several management commands for managing yourapplication's data.#### `buildsite`You should use this command to generate a static copy of your website's pages,so that it can be served by a webserver or static site host.This command first runs the `loadpages` command, to populate the application'sdatabase.  It then starts a local development server (via `runserver`), andcrawls the site, following every link starting at `/`.The crawled pages are written to the `output` directory.Additionally, if the `DJANGO_AMBER_CNAME` setting is set, a file is written tothe `output` directory whose contents is the value of this setting.  This isuseful for deploying to GitHub Pages.#### `serve`You should use this command in development, as a beefed-up version of`runserver`.This command takes an optional positional argument, the port on which to runthe server.  By default, this is `8000`.This command starts a local development server (via `runserver`) and serves theapplication as normal.Before the server starts, it runs the `loadpages` command to populate theapplication's database from the files serialized on the filesystem.While the server is running, this command watches for any changes to theserialized files on the filesystem, and updates the application's databaseaccordingly.#### `loadpages`You probably won't need need to invoke this command directly.This command deserializes the contents of the filesystem, and loads objectsinto the application's database.#### `dumppages`You probably won't need need to invoke this command directly.This command serializes the contents of the application's database to thefilesystem.### ModelsAll models whose data is serialized to the filesystem must inherit either from`ModelWithContent` or `ModelWithoutContent`, which are [abstract baseclasses](https://docs.djangoproject.com/en/1.9/topics/db/models/#abstract-base-classes)defined in `django_amber.models`.What follows is a description of these classes, including the fields theyprovide to their subclasses, and details of instances of these classes areserialized.  It is probably clearer to read the example later on.#### `django_amber.models.ModelWithContent`Subclasses of `ModelWithContent` are for models whose instances representobjects with a significant amount of content, for instance a whole web page, anews article, or a blog post.Subclasses inherit the following fields:* `key`: A `CharField` whose value identifies the model instance uniquely.This is used as the base of the filename when the model instance isserialized to the filesystem, and is also used when to identify related models(see below).* `content`: A `TextField` whose value is the content corresponding to the pagein question.* `content_format`: A `CharField` whose value is the file extensioncorresponding to the format of the content.  For instance, if the content is[Markdown](https://daringfireball.net/projects/markdown/), the value shouldbe `"md"`.  This is used as the file extension when the model instance isserialized to the filesystem.Subclasses can define any other fields as required.By default, instances of subclasses of `ModelWithContent` will be serialized tothe filesystem at `[app_label]]/data/[model_name]/[key].[content_format]`.This can be overridden by setting the `dump_path_dir` class variable.  See the`Article` model in `tests.models.py` for an example of this.The file containing a serialized model instance will have two parts.  Firstly,all fields, except for the three mentioned above, are serialized as YAML.`ForeignKey`s and `ManyToManyField`s are handled as described below.  Thenfollow three dashes (`---`), and then follows the value of the `content` field.#### `django_amber.models.ModelWithoutContent`Subclasses of `ModelWithoutContent` are for models whose instances representobjects that do not have a significant amount of content.Subclasses inherit the following field:* `key`: A `CharField` whose value identifies the model instance uniquely.This is used as the base of the filename when the model instance isserialized to the filesystem, and is also used when to identify related models(see below).Subclasses can define any other fields as required.By default, instances of subclasses of `ModelWithContent` will be serialized tothe filesystem at `[app_label]]/data/[model_name]/[key].yml`.  This can beoverridden by setting the `dump_path_dir` class variable.  See the`Article` model in `tests.models.py` for an example of this.The file containing a serialized model instance contains all fields, except for`key`, serialized as YAML.  `ForeignKey`s and `ManyToManyField`s are handled asdescribed below.#### Relationships between modelsThis is definitely easier explained by example... see below.If model `A` has a `ForeignKey` field to model `B`, when an instance `a` of `A`is serialized, the serialized value of `b` will be `a.b.key`.Similarly, if model `A` has a `ManyToManyField` field to model `C`, when aninstance `a` of `A` is serialized, the serialized value of `cs` will be thelist `[c.key for c in a.cs]`.To ensure that objects can be deserialized correctly, all `ForeignKey` fieldsmust have `null` set to `True`.### ExampleSuppose we want to build a site that displays articles on a range of topics.Each article has an author, and may have many tags.We have the following three models in an app called `myapp`.class Article(ModelWithContent):title = models.CharField(max_length=255)author = models.ForeignKey('Author', null=True)tags = models.ManyToManyField('Tag', related_name='articles')class Author(ModelWithoutContent):name = models.CharField(max_length=255)email = models.EmailField()class Tag(ModelWithoutContent):name = models.CharField(max_length=255)description = models.CharField(max_length=255)We can create instances of these models by creating some files on thefilesystem:```# myapp/pages/article/django.mdauthor: janetags:- djangotitle: All about Django---This is an article about *Django*.``````# myapp/metadata/author/jane.ymlname: Jane Smithemail: jane@example.com``````# myapp/metadata/tag/django.ymlname: Djangodescription: Django is the web framework for perfectionists with deadlines```(Alternatively, we could populate the Django database via eg the admin, andthen run the `dumppages` command to write the data to the filesystem.)## DevelopmentRun tests with `tox`.## About the name[Thales of Miletus](https://en.wikipedia.org/wiki/Thales) used amber togenerate static electricity.