Package: django-jackfrost
django-jackfrost 0.4.0Convert your Django views into a collection of static HTML files. Or, put
another way, a Django based static-site-generator with few opinions.This is my attempt at a different type of static site renderer, instead
leveraging the availability of Django’sstaticfilesfunctionality to leave
specifics to someone else :)
The theory is thus that you could choose a third party storage from, say,django-storagesand plug it intojackfrostand have things Just Work.I don’t actually know if that’s true though.ReleaseStatusstable (0.4.0)masterAlternativesThere’sdjango-medusa, though it doesn’t appear to be active anymore.alsodjango-bakery, which takes a different approach whereby one must
extend specific views or models.DifferencesUnlikedjango-medusathere is no autodiscovery, and no requirement that
renderers go in a specific place.Unlikedjango-bakery, existing views and models ought to be usable unchanged,
because of the renderer approach I’ve taken, which is more similar todjango-medusaorDjango RSS Feeds.DependenciesDjangopytestInstallingpipinstalling the latest release via PyPI:pip install django-jackfrost==0.4.0If you want to get the latest, unstable version, you can use
something like this (again withpip) I think:pip install git+https://github.com/kezabelle/django-jackfrost.git#egg=django-jackfrostPutjackfrostinto yourINSTALLED_APPS:INSTALLED_APPS = (
    'django.contrib.auth',
    # ...
    'jackfrost',
    # ...
)which will enable the management command:python manage.py collectstaticsite --processes=NConfiguration & usageSetJACKFROST_STORAGEto whatever storage backend you’d like to use, in
your project’s settings. By default, a subclass ofdjango.contrib.staticfiles.storage.StaticFilesStoragewhich puts output into
ajackfrostdirectory will be used.If your storage backend needs any arguments that can’t be gleaned from individual
settings, you can setJACKFROST_STORAGE_KWARGSto a dictionary of
arguments to be used when instantiating theJACKFROST_STORAGESelecting renderersAdd aJACKFROST_RENDERERSsetting, which should be a list or tuple of
dotted paths to python classes or functions, much likeMIDDLEWARE_CLASSES,TEMPLATE_CONTEXT_PROCESSORSetc:JACKFROST_RENDERERS = (
    'myapp.renderers.MyModelRenderer',
    'my_other_app.utils.SomeOtherRenderer',
)In theory, I don’t care whether yourJACKFROST_RENDERERSare functions
or classes; if it’s a class it must implement__call__. Either way,
it should, when called, return a number of URL paths to be consumed.Renderers for modelsIf you have a model which has aget_absolute_urlmethod, your renderer
can be as simple as:from jackfrost.models import ModelRenderer

class MyModelRenderer(ModelRenderer):
    def get_model(self):
        return MyModelIf you need to customise the queryset, there is aget_querysetmethod
which can be replaced. There is also aget_urlsmethod, if you need to
go totally off-reservation.Reading fromsitemapsGivingjackfrostthe dotted path to a standardDjango sitemapas
one of theJACKFROST_RENDERERSshould do the right thing, and get the
URLs out of the sitemap itself without you needing to do anything or write
a new renderer.Reading fromdjango-medusaIn theory, givingjackfrostthe dotted path to a subclass of thedjango-medusaBaseStaticSiteRenderershould do the right thing, and get the URLs out of
the medusa renderer itself, without you doing anything. It will avoid going
through the medusa rendering process, instead it’ll go through mine.Reading fromDjango RSS FeedsGivingjackfrostthe dotted path to a subclass of aFeedshould do the right thing, and get the URLs out by asking theFeedfor theitem_linkfor everything initems, without you doing anything.Writing a rendererThe most basic renderer would be:def myrenderer_yielding():
    yield reverse('app:name')or:def myrenderer():
    return [reverse('app:name')]Renderers may also be classes:class MyRenderer(object):
    __slots__ = ()

    def __init__(self):
        pass

    def __call__(self):
        yield reverse('app:name')Listening for rendersThere are 8 signals in total:build_startedis fired when the management command is run.reader_startedis fired when aURLReaderinstance begins working.read_pageis fired when aURLReadersuccessfully gets a URL’s content.reader_finishedis fired when aURLReaderinstance completes.writer_startedis fired when aURLWriterinstance begins working.write_pageis fired just after the content is written to the storage backend.writer_finishedis fired when theURLWritercompletesbuild_finishedfires at the end of the management command.Rendering on model changeAdditionally, there is a listener,jackfrost.utils.build_page_for_objwhich
is suitable for being used as apre_saveorpost_savereceiver for
aModelinstance, and will attempt to build just theget_absolute_urlfor
that object.Defining when a model may buildIf aModelinstance implements ajackfrost_can_buildmethod, this is
checked before building the static page. Ifjackfrost_can_buildreturnsFalse, the page won’t get built. Any other value will result in it being
built.Defining different URLsIf aModelinstance implements ajackfrost_urlsmethod, this
is used instead of theget_absolute_url, and should return an iterable of
all the URLs to consider building.If theModelinstance has aget_list_urlmethod, that page will also be
built. Useful for updating anyListViewpages, etc.ExtrasWhere possible,jackfrostwill attempt to compensate for redirects (301, 302 etc)
by writing an HTML page with a<meta refresh>tag pointing at the final
endpoint. The template used is called301.html.Additionally, static pages for 401, 403, 404 and 500 errors will be built
from their respective templates, if they exist. Useful if you want to wire
up ApacheErrorDocumentdirectives or whatever.Running the tests (87% coverage)Given a complete clone:python setup.py testLicensedjango-jackfrost0.4.0is available under the terms of the
Simplified BSD License (alternatively known as the FreeBSD License, or
the 2-clause License):Copyright (c) 2015, Keryn Knight
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.Change log0.4.0Addedsignals.write_pagewhich is fired after the storage backend has
written the content.Addedutils.eventlog_writefor usingpinax.eventlogand the
aforementionedwrite_pagesignal to track built items.Added aModelAdmin actionfor building a selection of model instances
into their static counterparts, from the admin changelist.Made the receiverutils.build_page_for_objactually work.themodelsmodule will be compiled using Cython, if installed.0.3.0Replacedjackfrost_absolute_urlmethod inModelRendererwithjackfrost_urls, which allows models to add every URL they want to cause
to be visited.0.2.1Added support for Django 1.6Added celery tasks for building both a single URL, and all URLs.0.2.0Initial release.