borgcube.web package¶
borgcube.web.core.hookspec module¶
borgcube.web.core.middleware module¶
borgcube.web.core.templatetags.borgcube module¶
Return URL for model_instance.
This has some core classes coded in and otherwise works through
hookspec.borgcube_web_get_url
.
Format a
datetime.timedelta
instance to a human-friendly format.
Look value of an object up through a variable (instead of a fixed name as in obj.a)
Return safe JSON serialization (as in: use in <script>-tags) of obj.
Describe a
recurrence.Recurrence
object in human terms.Due to the possible complexities of recurrences this only works for simple recurrences, complex ones will return a non-descript description.
borgcube.web.core.publishers package¶
-
class
borgcube.web.core.publishers.
PublisherMenu
[source]¶ Bases:
object
Defines the interface for exposing menu entries directly by publishers.
Note that there is no way to specify an URL; the menu entry always points to the default view of the instance.
Whether this publisher should be included. When absent, False.
The text of the item. Normally a lazy translation object (eg.
ugettext_lazy
).
-
class
borgcube.web.core.publishers.
Publisher
(companion)[source]¶ Bases:
object
Core class of the object publishing system.
Since the core of BorgCube is not tied to the web interface, objects do not directly implement object publishing protocols like usually done in eg. Zope or Pyramid.
Instead a second hierarchy of object exists, the publishers, that only contain web- related functionality. Every publisher instance is bound to a companion, the core object that it renders. The
companion
attribute defines how the instance attribute shall be named.A publisher can have multiple views, but by default only has it’s default view.
A publisher can either have a “relatively static” number of children, by implementing
children
and returning a mapping of segments to child publisher instances or factories, or a “rather dynamic” number of children, by implementing__getitem__
.The first case is usually used if the children are static, eg. the
RootPublisher
has fixed children (ClientsPublisher
,SchedulesPublisher
, …), while the second case is best applied if the children are sourced from the database, since only one publisher, for the requested child, needs to be constructed.An example best illustrates this:
class RootPublisher(Publisher): companion = 'dr' def children(self): return { 'clients': ClientsPublisher(self.dr.clients), 'schedules': SchedulesPublisher(self.dr.schedules), # ... }
On the other hand, here is how
ClientsPublisher
handles it’s children:class ClientsPublisher(Publisher): companion = 'clients' def __getitem__(self, hostname): client = self.clients[hostname] return ClientPublisher(client)
Note that, since
ClientsPublisher
was provided byRootPublisher
the companion ofClientsPublisher
isdata_root().clients
– so__getitem__
here only loads the required client from the database.Also note how no extra error handling is required: clients is already a mapping itself, so if no client with hostname exists it will raise
KeyError
.This might seem a bit confusing and convoluted, however, it allows implicit URL generation and avoids having to define many URL patterns by hand. It also decouples components very efficiently, since URLs are both resolved and generated by the hierarchy, so plugins can just “hook into” the system and don’t need to bother defining URLs that don’t conflict with core URLs.
Additional views
Additional views can be added by adding something_view methods and adding it to the
views
property:class MyPublisher(Publisher): views = ('edit', ) def view(self, request): ... def edit_view(self, request): ...
In the URL hierarchy these are addressed through the
view
query parameter, eg. /clients/foo/?view=edit. The query parameter converts dashes to underscores, eg. ?view=latest_job and ?view=latest-job are identical.-
companion
= 'companion'¶ The name of the companion attribute
-
views
= ()¶ Exposed views (the default view is always exposed), base names, no trailing
_view
.
-
name
¶ Name of the publisher for hookspec purposes. Defaults to class.companion.
-
get
(segment)[source]¶ Return child from segment or raise KeyError.
First tries subscription (
__getitem__
), then looks up inchildren
. Ensures that child.segment and child.parent are set correctly.
-
children
()[source]¶ Return a mapping of child names to child publishers.
Make sure to call into
children_hook
, like so:def children(self): return self.children_hook({ ... })
-
children_hook
(children)[source]¶ Post-process result of
children
.This adds plugin children via
borgcube_web_children
and ensures that all children know their parent and segment.
-
redirect_to
(view=None, permanent=False)[source]¶ Return a HTTP redirect response to this publisher and view.
-
resolve
(path_segments, view=None)[source]¶ Resolve reversed path_segments to a view or raise
Http404
.Note: path_segments is destroyed in the process.
-
render
(request, template=None, context={})[source]¶ Return a TemplateResponse for request, template and context.
The actual context is constructed by obtaining the return of
context
and updating that with the passed context.If template is None, then the
base_template
is used.
-
context
(request)[source]¶ Return the “base context” for request.
Make sure to always call the base implementation, which provides the following keys:
- publisher (self)
- cls.companion (correctly named companion obtained from self.get_companion())
- base_template
- secondary_menu (None, overridden in subclasses)
-
-
class
borgcube.web.core.publishers.
ExtensiblePublisher
(companion)[source]¶ Bases:
borgcube.web.core.publishers.Publisher
,borgcube.web.core.publishers.PublisherMenu
An extensible publisher implements publishers which are extended by
ExtendingPublisher
s.This allows to decouple the publishing of child objects from the publisher of an object, by allowing other parts and plugins to hook into the display and present their content wrapped up in your visual framework.
An extensible publisher always has a menu entry that is used for secondary navigation between the ExtensiblePublisher and a number of ExtendingPublishers, which appear at the same level (although the are technically subordinate).
The extending publishers are attached in the regular way through
children_hook
.Templates and contexts
An extensible publisher should designate a template with
default_template
whosetitle
andctitle
blocks are renderable with the standardcontext
. ExtendingPublishers will use this to render their content into the ccontent block (indirectly).-
context
(request)[source]¶ Return the “base context” for request.
Make sure to always call the base implementation, which provides the following keys:
- publisher (self)
- cls.companion (correctly named companion obtained from self.get_companion())
- base_template
- secondary_menu (None, overridden in subclasses)
-
default_template
(request)[source]¶ Return default template name (see class docstring). Default:
base_template
-
-
class
borgcube.web.core.publishers.
ExtendingPublisher
(companion)[source]¶ Bases:
borgcube.web.core.publishers.Publisher
,borgcube.web.core.publishers.PublisherMenu
-
render
(request, template=None, context=None)[source]¶ Return a TemplateResponse for request, template and context.
The actual context is constructed by obtaining the return of
context
and updating that with the passed context.If template is None, then the
base_template
is used.
-