Snippets and some reorg

pull/256/head
Jeffrey Hearn 2014-05-13 22:38:44 -04:00
rodzic b42a0d2cf0
commit a2ed70bd8d
6 zmienionych plików z 250 dodań i 154 usunięć

Wyświetl plik

@ -0,0 +1,9 @@
Advanced Topics
~~~~~~~~~~~~~~~~
replacing image processing backend
custom image processing tags?
wagtail user bar custom CSS option?

Wyświetl plik

@ -1,22 +1,22 @@
Building your site
==================
Model Design with Wagtail
~~~~~~~~~~~~~~~~~~~~~~~~~
Wagtail manages content internally as a tree of pages. Each node in the tree is an instance of a Django model which subclasses the Wagtail ``Page`` class. You define the structure and interrelationships of your Wagtail site by coding these models and then publishing pages which use the models through the Wagtail admin interface.
The Page Class
~~~~~~~~~~~~~~
``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some fields and editing handlers that simplify data entry in the Wagtail admin interface, so you may want to keep those in mind when deciding what properties to add to your models in addition to those already provided by ``Page``.
Built-in Properties of the Page Class
-------------------------------------
Wagtail provides some properties in the Page class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them.
Wagtail provides some properties in the ``Page`` class which are common to most webpages. Since you'll be subclassing ``Page``, you don't have to worry about implementing them.
Public Properties Suitable for Inclusion in Templates
`````````````````````````````````````````````````````
Public Properties
`````````````````
``title`` (string, required)
Human-readable title for the content
@ -30,32 +30,23 @@ Public Properties Suitable for Inclusion in Templates
``search_description`` (string)
A SEO-crafted description of the content, used in both internal search indexing and for the meta description read by search engines
Semi-Private Properties Intended for Use in the Wagtail Admin
`````````````````````````````````````````````````````````````
The ``Page`` class actually has alot more to it, but these are probably the only built-in properties you'll need to worry about when creating templates for your models.
Anatomy of a Wagtail Model
~~~~~~~~~~~~~~~~~~~~~~~~~~
So what does a Wagtail model definition look like?
``show_in_menus`` (boolean)
Whether a link to this page will appear in automatically generated menus"))
``live`` (boolean)
Whether the page is in a published, public-visible state
``has_unpublished_changes`` (boolean)
Whether the page is in a draft state
``owner`` (User)
Model relation pointing to the user who owns the page. Uses the user model set in ``settings.AUTH_USER_MODEL``.
``indexed_fields`` (dict)
Describes the properties which should be indexed by search and how they should be weighted for maximum accuracy. See the Search section for usage.
Internal Properties Which Describe The Model Instance
`````````````````````````````````````````````````````
``content_type`` (ContentType)
A relation to an internal content type model.
``url_path`` (string)
The full URL path, including the slugs of all parents going back to the site root. Whenever a slug is changed in the tree, all of the node's descendants are updated with the new path. Use the ``pageurl`` template tag for outputting the URL of a page-subclassed object.
Introduction to Trees
---------------------
@ -78,10 +69,10 @@ The Wagtail admin interface uses the tree to organize content for editing, letti
Nodes and Leaves
----------------
It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves.
It might be handy to think of the ``Page``-derived models you want to create as being one of two node types: parents and leaves. Wagtail isn't prescriptive in this approach, but it's a good place to start if you're not experienced in structuring your own content types.
Parents
```````
Nodes
`````
Parent nodes on the Wagtail tree probably want to organize and display a browsable index of their descendents. A blog, for instance, needs a way to show a list of individual posts.
A Parent node could provide its own function returning its descendant objects.
@ -127,11 +118,12 @@ Other Relationships
```````````````````
Your ``Page``-derived models might have other interrelationships which extend the basic Wagtail tree or depart from it entirely. You could provide functions to navigate between siblings, such as a "Next Post" link on a blog page (``post->post->post``). It might make sense for subtrees to interrelate, such as in a discussion forum (``forum->post->replies``) Skipping across the hierarchy might make sense, too, as all objects of a certain model class might interrelate regardless of their ancestors (``events = EventPage.objects.all``). Since there's no restriction on the combination of model classes that can be used at any point in the tree, and it's largely up to the models to define their interrelations, the possibilities are really endless.
Model Recipes
-------------
~~~~~~~~~~~~~
Overriding the Serve() Method
`````````````````````````````
-----------------------------
Wagtail defaults to serving ``Page``-derived models by passing ``self`` to a Django HTML template matching the model's name, but suppose you wanted to serve something other than HTML? You can override the ``serve()`` method provided by the ``Page`` class and handle the Django request and response more directly.
@ -164,7 +156,8 @@ Consider this example from the Wagtail demo site's ``models.py``, which serves a
With this strategy, you could use Django or Python utilities to render your model in JSON or XML or any other format you'd like.
Tagging
```````
-------
Wagtail provides tagging capability through the combination of two django modules, ``taggit`` and ``modelcluster``. ``taggit`` provides a model for tags which is extended by ``modelcluster``, which in turn provides some magical database abstraction which makes drafts and revisions possible in Wagtail. It's a tricky recipe, but the net effect is a many-to-many relationship between your model and a tag class reserved for your model.
Using an example from the Wagtail demo site, here's what the tag model and the relationship field looks like in ``models.py``:
@ -227,69 +220,6 @@ This is just one possible way of creating a taxonomy for Wagtail objects. With a
ParentalKey for storing groups of stuff to a Page-thing
Using or subclassing the site model?
Wagtail Admin API
~~~~~~~~~~~~~~~~~
Fields & Edit Handlers
----------------------
RichTextField
Image
FieldPanel
MultiFieldPanel
InlinePanel
PageChooserPanel
ImageChooserPanel
DocumentChooserPanel
Snippets
--------
Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``.
Here's an example snippet from the Wagtail demo website:
.. code-block:: python
class Advert(models.Model):
page = models.ForeignKey(
'wagtailcore.Page',
related_name='adverts',
null=True,
blank=True
)
url = models.URLField(null=True, blank=True)
text = models.CharField(max_length=255)
panels = [
PageChooserPanel('page'),
FieldPanel('url'),
FieldPanel('text'),
]
def __unicode__(self):
return self.text
register_snippet(Advert)
The ``Advert`` model uses the basic Django model class and defines three properties: text, url, and page. The editing interface is very close to that provided for ``Page``-derived models, with fields assigned in the panels property.
@ -372,32 +302,14 @@ Template Filters
Site
~~~~
Django's built-in admin interface provides the way to map a "site" (hostname or domain) to the root of a wagtail tree. Access this by going to ``/django-admin/`` and then "Home Wagtailcore Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created.
Advanced Wagtail
~~~~~~~~~~~~~~~~
replacing image processing backend
custom image processing methods?
wagtail user bar custom CSS option?
Django's built-in admin interface provides the way to map a "site" (hostname or domain) to any node in the wagtail tree, using that node as the site's root.
Access this by going to ``/django-admin/`` and then "Home Wagtailcore Sites." To try out a development site, add a single site with the hostname ``localhost`` at port ``8000`` and map it to one of the pieces of content you have created.
Wagtail's developers plan to move the site settings into the Wagtail admin interface.

Wyświetl plik

@ -10,7 +10,10 @@ It supports Django 1.6.2+ on Python 2.6 and 2.7. Django 1.7 and Python 3 support
gettingstarted
building_your_site
panels
snippets
wagtail_search
advanced_topics
deploying
performance
contributing

33
docs/panels.rst 100644
Wyświetl plik

@ -0,0 +1,33 @@
Panels & Edit Handlers
======================
RichTextField
~~~~~~~~~~~~~
Image
~~~~~
FieldPanel
~~~~~~~~~~
MultiFieldPanel
~~~~~~~~~~~~~~~
InlinePanel
~~~~~~~~~~~
PageChooserPanel
~~~~~~~~~~~~~~~~
ImageChooserPanel
~~~~~~~~~~~~~~~~~
DocumentChooserPanel
~~~~~~~~~~~~~~~~~~~~
SnippetChooserPanel
~~~~~~~~~~~~~~~~~~~

140
docs/snippets.rst 100644
Wyświetl plik

@ -0,0 +1,140 @@
Snippets
========
Snippets are pieces of content which do not necessitate a full webpage to render. They could be used for making secondary content, such as headers, footers, and sidebars, editable in the Wagtail admin. Snippets are models which do not inherit the ``Page`` class and are thus not organized into the Wagtail tree, but can still be made editable by assigning panels and identifying the model as a snippet with ``register_snippet()``.
Snippets are not searchable or orderable in the Wagtail admin, so decide carefully if the content type you would want to build into a snippet might be more suited to a page.
Snippet Models
--------------
Here's an example snippet from the Wagtail demo website:
.. code-block:: python
from django.db import models
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailsnippets.models import register_snippet
...
class Advert(models.Model):
url = models.URLField(null=True, blank=True)
text = models.CharField(max_length=255)
panels = [
FieldPanel('url'),
FieldPanel('text'),
]
def __unicode__(self):
return self.text
register_snippet(Advert)
The ``Advert`` model uses the basic Django model class and defines two properties: text and url. The editing interface is very close to that provided for ``Page``-derived models, with fields assigned in the panels property. Snippets do not use multiple tabs of fields, nor do they provide the "save as draft" or "submit for moderation" features.
``register_snippet(Advert)`` tells Wagtail to treat the model as a snippet. The ``panels`` list defines the fields to show on the snippet editing page. It's also important to provide a string representation of the class through ``def __unicode__(self):`` so that the snippet objects make sense when listed in the Wagtail admin.
Including Snippets in Template Tags
-----------------------------------
The simplest way to make your snippets available to templates is with a template tag. This is mostly done with vanilla Django, so perhaps reviewing Django's documentation for `django custom template tags`_ will be more helpful. We'll go over the basics, though, and make note of any considerations to make for Wagtail.
First, add a new python file to a ``templatetags`` folder within your app. The demo website, for instance uses the path ``wagtaildemo/demo/templatetags/demo_tags.py``. We'll need to load some Django modules and our app's models and ready the ``register`` decorator:
.. _django custom template tags: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
.. code-block:: python
from django import template
from demo.models import *
register = template.Library()
...
# Advert snippets
@register.inclusion_tag('demo/tags/adverts.html', takes_context=True)
def adverts(context):
return {
'adverts': Advert.objects.all(),
'request': context['request'],
}
``@register.inclusion_tag()`` takes two variables: a template and a boolean on whether that template should be passed a request context. It's a good idea to include request contexts in your custom template tags, since some Wagtail-specific template tags like ``pageurl`` need the context to work properly. The template tag function could take arguments and filter the adverts to return a specific model, but for brevity we'll just use ``Advert.objects.all()``.
Here's what's in the template used by the template tag:
.. code-block:: django
{% for advert in adverts %}
<p>
<a href="{{ advert.url }}">
{{ advert.text }}
</a>
</p>
{% endfor %}
Then in your own page templates, you can include your snippet template tag with:
.. code-block:: django
{% block content %}
...
{% adverts %}
{% endblock %}
Binding Pages to Snippets
-------------------------
An alternate strategy for including snippets might involve explicitly binding a specific page object to a specific snippet object. Lets add another snippet class to see how that might work:
.. code-block:: python
from django.db import models
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.edit_handlers import PageChooserPanel
from wagtail.wagtailsnippets.models import register_snippet
from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel
from modelcluster.fields import ParentalKey
...
class AdvertPlacement(models.Model):
page = ParentalKey('wagtailcore.Page', related_name='advert_placements')
advert = models.ForeignKey('demo.Advert', related_name='+')
class Meta:
verbose_name = "Advert Placement"
verbose_name_plural = "Advert Placements"
panels = [
PageChooserPanel('page'),
SnippetChooserPanel('advert', Advert),
]
def __unicode__(self):
return self.page.title + " -> " + self.advert.text
register_snippet(AdvertPlacement)
The class ``AdvertPlacement`` has two properties, ``page`` and ``advert``, which point to other models. Wagtail provides a ``PageChooserPanel`` and ``SnippetChooserPanel`` to let us make painless selection of those properties in the Wagtail admin. Note also the ``Meta`` class, which you can stock with the ``verbose_name`` and ``verbose_name_plural`` properties to override the snippet labels in the Wagtail admin. The text representation of the class has also gotten fancy, using both properties to construct a compound label showing the relationship it forms between a page and an Advert.
With this snippet in place, we can use the reverse ``related_name`` lookup label ``advert_placements`` to iterate over any placements within our template files. In the template for a ``Page``-derived model, we could include the following:
.. code-block:: django
{% if self.advert_placements %}
{% for advert_placement in self.advert_placements.all %}
<p><a href="{{ advert_placement.advert.url }}">{{ advert_placement.advert.text }}</a></p>
{% endfor %}
{% endif %}

Wyświetl plik

@ -68,7 +68,43 @@ The search view provides a context with a few useful variables.
``query``
A Wagtail ``Query`` object matching the terms. The ``Query`` model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. ``Query`` also joins to the Editor's Picks functionality though ``query.editors_picks``. See :ref:`editors-picks`.
Editor's Picks
--------------
Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties.
``query.editors_picks.all``
This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties:
``editors_pick.page``
The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object.
``editors_pick.description``
The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms.
Putting this all together, a block of your search results template displaying Editor's Picks might look like this:
.. code-block:: django
{% with query.editors_picks.all as editors_picks %}
{% if editors_picks %}
<div class="well">
<h3>Editors picks</h3>
<ul>
{% for editors_pick in editors_picks %}
<li>
<h4>
<a href="{% pageurl editors_pick.page %}">
{{ editors_pick.page.title }}
</a>
</h4>
<p>{{ editors_pick.description|safe }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
Asyncronous Search with JSON and AJAX
-------------------------------------
@ -81,7 +117,7 @@ Wagtail's provides JSON search results when queries are made to the ``wagtailsea
var wagtailJSONSearchURL = "{% url 'wagtailsearch_suggest' %}";
</script>
Lets also add a simple interface for the search with an ``<input>`` element and ``<div>`` for the results:
Lets also add a simple interface for the search with a ``<input>`` element to gather search terms and a ``<div>`` to display the results:
.. code-block:: html
@ -162,43 +198,6 @@ In this template, you'll have access to the same context variablies provided to
.. _editors-picks:
Editor's Picks
--------------
Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties.
``query.editors_picks.all``
This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties:
``editors_pick.page``
The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object.
``editors_pick.description``
The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms.
Putting this all together, a block of your search results template displaying Editor's Picks might look like this:
.. code-block:: django
{% with query.editors_picks.all as editors_picks %}
{% if editors_picks %}
<div class="well">
<h3>Editors picks</h3>
<ul>
{% for editors_pick in editors_picks %}
<li>
<h4>
<a href="{% pageurl editors_pick.page %}">
{{ editors_pick.page.title }}
</a>
</h4>
<p>{{ editors_pick.description|safe }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
Indexing Custom Fields & Custom Search Views
--------------------------------------------