Base Models¶
-
class
widgy.models.base.
Content
[source]¶ -
Tree Traversal
With the exception
depth_first_order()
, the following methods are all like the traversal API provided byTreebeard
, but instead of returningNodes
, they returnContents
.-
depth_first_order
(self)[source]¶ Convenience method for iterating over all the
Contents
in a subtree in order. This is similar to Treebeard’sget_descendants()
, but includes itself.
Tree Manipulation
The following methods mirror those of
Node
, but accept aWidgySite
as the first argument. You must call these methods onContent
and not onNode
.>>> root = Layout.add_root(widgy_site) >>> main = root.add_child(widgy_site, MainContent) >>> sidebar = main.add_sibling(widgy_site, Sidebar, title='Alerts') # move the sidebar to the left of the main content. >>> sidebar.reposition(widgy_site, right=main)
-
classmethod
add_root
(cls, site, **kwargs)[source]¶ Creates a root node widget. Any kwargs will be passed to the Content class’s initialize method.
-
add_child
(self, site, cls, **kwargs)[source]¶ Adds a new instance of
cls
as the last child of the current widget.
-
add_sibling
(self, site, cls, **kwargs)[source]¶ Adds a new instance of
cls
to the right of the current widget.
-
reposition
(self, site, right=None, parent=None)[source]¶ Moves the current widget to the left of
right
or to the last child position ofparent
.
-
post_create
(self, site)[source]¶ Hook for doing things after a widget has been created (a
Content
has been created and put in the tree). This is useful if you want to have default children for a widget, for example.
-
delete
(self, raw=False)[source]¶ If
raw
isTrue
the widget is being deleted due to a failure in widget creation, sopost_create
will not have been run yet.
-
clone
(self)[source]¶ This method is called by
Node.clone_tree()
. You may wish to override it if your Content has special needs like a ManyToManyField.Warning
Clone is used to freeze tree state in Versioning. If your
clone()
method is incorrect, your history will be corrupt.
Editing
-
display_name
¶ A human-readable short name for widgets. This defaults to the
verbose_name
of the widget.Hint
You can use the
@property
decorator to make this dynamic.Todo
screenshot
-
tooltip
¶ A class attribute that sets the tooltip for this widget on the shelf.
-
css_classes
¶ A list of CSS classes to apply to the widget element in the Editor. Defaults to
app_label
andmodule_name
of the widget.
-
shelf = False
Denotes whether this widget have a shelf. Root nodes automatically have a shelf. The shelf is where the widgets exist in the interface before they are dragged on. It is useful to set
shelf
toTrue
if there are a large number of widgets who can only go in a specfic subtree.
-
component_name = 'widget'
Specifies which JavaScript component to use for this widget.
Todo
Write documentation about components.
-
pop_out = CANNOT_POP_OUT
It is possible to open a subtree in its own editing window.
pop_out
controls if a widget can be popped out. There are three values forpop_out
:-
CANNOT_POP_OUT
¶
-
CAN_POP_OUT
¶
-
MUST_POP_OUT
¶
-
-
form = ModelForm
The form class to use for editing. Also see
get_form_class()
.
-
formfield_overrides = {}
Similar to
ModelAdmin
,Content
allows you to override the form fields for specific model field classes.
-
draggable = True
Denotes whether this widget may be moved through the editing interface.
-
deletable = True
Denotes whether this widget may be deleted through the editing interface.
-
editable = False
Denotes whether this widget may be edited through the editing interface. Widgy will automatically generate a
ModelForm
to provide the editing functionality. Also seeform
andget_form_class()
.
-
preview_templates
¶ A template name or list of template names for rendering in the widgy Editor. See
get_templates_hierarchy()
for how the default value is derived.
-
edit_templates
¶ A template name or list of template names for rendering the edit interface in the widgy Editor. See
get_templates_hierarchy()
for how the default value is derived.
-
classmethod
get_templates_hierarchy
(cls, **kwargs)[source]¶ Loops through MRO to return a list of possible template names for a widget. For example the preview template for something like
Tabs
might look like:widgy/page_builder/tabs/preview.html
widgy/mixins/tabbed/preview.html
widgy/page_builder/accordion/preview.html
widgy/page_builder/bucket/preview.html
widgy/models/content/preview.html
widgy/page_builder/preview.html
widgy/mixins/preview.html
widgy/page_builder/preview.html
widgy/models/preview.html
widgy/preview.html
Frontend Rendering
-
render
(self, context, template=None)[source]¶ The method that is called by the
render()
template tag to render the Content. It is useful to override this if you need to inject things into the context.
-
get_render_templates
(self, context)[source]¶ Returns a template name or list of template names for frontend rendering.
Compatibility
Widgy provide robust machinery for compatibility between Contents. Widgy uses the compatibility system to validate the relationships between parent and child Contents.
Compatibility is checked when rendering the shelf and when adding or moving widgets in the tree.
-
accepting_children = False
An easy compatibility configuration attribute. See
valid_parent_of()
for more details.
-
valid_parent_of
(self, cls, obj=None)[source]¶ If
obj
is provided, returnTrue
if it could be a child of the current widget.cls
is the type ofobj
.If
obj
isn’t provided, returnTrue
if a new instance ofcls
could be a child of the current widget.obj
isNone
when the child widget is being created or Widgy is checking the compatibility of the widgets on the shelf. If it is being moved from another location, there will be an instance. A parent and child are only compatible if bothvalid_parent_of()
andvalid_child_of()
returnTrue
. This defaults to the value ofaccepting_children
.Here is an example of a parent that only accepts three instances of
B
:class A(Content): def valid_parent_of(self, cls, obj=None): # If this is already my child, it can stay my child. # This works for obj=None because self.get_children() # will never contain None. if obj in self.get_children(): return True else: # Make sure it is of type B return (issubclass(cls, B) # And that I don't already have three children. and len(self.get_children()) < 3)
-
classmethod
valid_child_of
(cls, parent, obj=None)[source]¶ If
obj
is provided, returnTrue
if it can be a child ofparent
.obj
will be an instance ofcls
—it may feel like an instance method.If
obj
isn’t provided, returnTrue
if a new instance ofcls
could be a child ofparent
.This defaults to
True
.Here is an example of a Content that can not live inside another instance of itself:
class Foo(Content): @classmethod def valid_child_of(cls, parent, obj=None): for p in list(parent.get_ancestors()) + [parent]: if isinstance(p, Foo): return False return super(Foo, cls).valid_child_of(parent, obj)
-
-
class
widgy.models.base.
Node
[source]¶ -
-
is_frozen
¶ A boolean field indicating whether this node is frozen and can’t be changed in any way. This is used to preserve old tree versions for versioning.
-
render
(self, *args, **kwargs)[source]¶ Renders this subtree and returns a string. Normally you shouldn’t call it directly, use
widgy.db.fields.WidgyField.render()
orwidgy.templatetags.widgy_tags.render()
.
-
depth_first_order
(self)[source]¶ Like
Content.depth_first_order()
, but over nodes.
-
prefetch_tree
(self)[source]¶ Efficiently fetches an entire tree (or subtree), including content instances. It uses
1 + m
queries, wherem
is the number of distinct content types in the tree.
-
classmethod
prefetch_trees
(cls, *root_nodes)[source]¶ Prefetches multiple trees. Uses
n + m
queries, wheren
is the number of trees andm
is the number of distinct content types across all the trees.
-
classmethod
find_widgy_problems
(cls, site=None)[source]¶ When a Widgy tree is edited without protection from a transaction, it is possible to get into an inconsistent state. This method returns a tuple containing two lists:
- A list of node pks whose content pointer is dangling – pointing to a content that doesn’t exist.
- A list of node pks whose content_type doesn’t exist. This might
happen when you switch branches and remove the code for a widget,
but still have the widget in your database. These are represented
by
UnknownWidget
instances.
-