-
Notifications
You must be signed in to change notification settings - Fork 1
/
README
258 lines (189 loc) · 7.84 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
=============== Wagtail Commons ===============
About
-----
While working on two different Wagtail sites, here are some things I
used... *on both of them*.
Installation
------------
::
pip install -e git://github.com/bgrace/wagtail-commons.git#egg=wagtail-commons --upgrade
Add to ``INSTALLED_APPS``:
::
INSTALLED_APPS = (
...
wagtail_commons.core,
...
)
Management command: bootstrap\_content
--------------------------------------
This adds a Django management command which will recursively import a
directory of .yml files, in order to create pages in an instance of
Wagtail CMS.
Introduction
~~~~~~~~~~~~
This is a django management commend for use with Wagtail that
recursively consumes a directory with yaml-based front matter and
markdown contents. For example, if you have the following files:
::
foo.yml
foo/bar.yml
foo/baz.yml
Where foo.yml looks like:
::
---
title: Is Lorem Really Ipsum?
type: demo.standardpage
--- @body
Lorem ipsum *blah blah* dolor blah blah
And the other pages, are similar, you will get the pages /foo/,
/foo/bar/ and /foo/baz/. Each one is instantiated according the ``type``
attribute found in the first yaml doc. For delimiters of the form
::
--- @some_attr
the script will consume the entire contents, render it as markdown, and
then assign the result to the attrribute ``some_attr``.
**WARNING**: This command is destructive by design. It finds your root
page, *deletes it and everything below it*, and creates a brand new
root. So if you have put content in your database, it will be gone after
you run it. It is intended to be executed repeatedly as you evolve your
content, and meant to discourage creating content "by hand" during the
design/development phase.
Invocation
~~~~~~~~~~
Run as
``python manage.py bootstrap_content --content <page definitions directory> --owner <username>``
For example:
``./manage.py bootstrap_content --content ../resources/content --owner johndoe``
Page owner
~~~~~~~~~~
Wagtail expects each page to have an owner. You must supply the username
of a Django user who will be the owner the Pages that will be created
with the ``--owner`` argument. This is a required argument.
Content Directory Structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Use the ``--content`` argument to tell the importer where to begin
searching for content. The example command above will look at
``../resources/content/pages.yml`` for some configuration, and then it
will recursively consume the contents of ``../resources/content/pages``,
looking for any file with an extension of ``.yml``.
pages.yml
^^^^^^^^^
The attributes in pages.yml will be added to every page definition,
unless the page definition provides a value. For example, most of the
pages in one of my projects are of type 'core.standardpage'. So my
pages.yml looks like:
::
---
type: core.standardpage
---
Page definition files
^^^^^^^^^^^^^^^^^^^^^
Page definition files are a mixture of YAML and markdown, with a .yml
extension. The command uses, or perhaps abuses, the YAML concept of
embedding multiple documents in a single file, and recognizes an
alternative syntax to embed multiple markdown documents. While this is
grotesquely out of spec for both parsers, it seems friendly to the
humans who have to edit it.
For example, suppose a page definition file is placed at
``contents/pages/lorem.yml`` and it looks like this:
::
---
type: demo.standardpage
title: Lorem in the Mist
--- @intro
A brief history of *lorem ipsum*.
--- @body
## The early years
Lorem ipsum was first ipsetur dolet sinatra lectibemur indemus
singlemaltscotchitum et valar morghulis megatonda whimsy.
Et cetera ceteribus
The document must begin with ``---`` on a line by itself in order to be
interpeted as YAML by the YAML parser. Any attributes defined in the
section will be applied to the Page object. After the first YAML
document is consumed, the command will look for documents delimeted by
``--- @some_attr``, where ``some_attr`` corresponds to some (for now,
string-based) Django model field. The markdown processor will convert
the contents to HTML, which will be assigned to the corresponding
attribute. Currently this command only supports attributes that can be
assigned to fields expecting string data. In other words there is a
**huge, gaping hole in its capabilities**. Sorry about that. I'll
probably need to add it for my own purposes, so sit tight.
For example, the above example will be interpreted in the following way:
- Create a new page object of type demo.StandardPage
- Make its owner the ``User`` object corresponding to the ``--owner``
flag
- Set the URL path of the page to ``/lorem/`` (inferred by placement in
the contents directory)
- Set the ``title`` of the page to 'Lorem in the Mist'
- Set the ``intro`` of the page to "A brief history of <i>lorem
ipsum</i>"
- Set the ``body`` of the page to "<h2>The early years</h2>..." (and so
on)
Directory layout and site map
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In general, the directory layout is the sitemap. The slug for the Page
is inferred from the path leading to the page definition, and the name
of the page definition file, less the extension. So a page found at
``$CONTENT_ROOT/pages/kingdom/phyllum/class/order/species/roygbiv.yml``
would have the URL path
``/kingdom/phyllum/class/order/species/roygbiv/``. However, you need to
have a page definition present at every intermediate level. So you would
actually need:
::
pages/kingdom.yml
pages/kingdom/phyllum.yml
pages/kingdom/phyllum/class.yml
pages/kingdom/phyllum/class/order.yml
pages/kingdom/phyllum/class/species.yml
pages/kingdom/phyllum/class/species/roygbiv.yml
(Note: I believe that this is an intrinsic limitation of Wagtail, since
each Page must have a parent.)
Defining the root page
~~~~~~~~~~~~~~~~~~~~~~
Your site needs a home page, with a url path of ``/``. But you're not
going to call your page definition ``/.yml``, right? Right. Fortunately,
your YAML front matter can contain an optional attribute, ``path``,
which overrides inferred URL. *You must* have a page definition with:
::
---
path: /
(... other attributes)
For example, one of my sites has a file ``pages/home.yml``, which looks
like this:
::
---
path: /
title: Home
type: core.homepage
--- @body
Lorem facta est
It doesn't matter where in the content directory hierarchy this file
exists. In fact, you can use the ``path`` override to enforce a
completely flat directory layout. The path-based URL inference is purely
a convenience.
PathOverrideable mixin for Page
-------------------------------
I created this package for myself as a repository of Wagtail
miscellanea. The first one of which is a way for a Page to override the
template based on the URL which it is attempting to serve.
PathOverrideable is mixin for Page classes, which reimplements the
Page.get\_template method. It allows the page template to be overriden
based on the incoming request's URL path. For example, it allows the
designer to supply a different template for ``/foo/``, ``/foo/bar/``,
and ``/foo/baz/``. Simply provide a template with the appropriate path
name. For example, supposing your ``TEMPLATE_DIRS`` contains
``templates``, simply provide:
::
templates/default/foo.html
templates/default/foo/bar.html
templates/default/foo/baz.html
Assuming that the pages at ``/foo/bar/`` and ``/foo/baz/`` are of type
``QuxPage``, then they may also be overriden as follows:
::
templates/default/foo/qux_page.html
This will override the template for every page of type ``QuxPage`` which
has ``/foo/`` as an ancestor.
In all cases, if an override cannot be found, the value of the Page
object's ``template`` property will be returned, i.e., whatever template
would normally be selected in the absence of this mixin.
Inspired by Mezzanine's template-lookup approach.