tutorial.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. Your first Wagtail site
  2. =======================
  3. 1. Install Wagtail and its dependencies::
  4. pip install wagtail
  5. 2. Start your site::
  6. wagtail start mysite
  7. cd mysite
  8. Wagtail provides a ``start`` command similar to
  9. ``django-admin.py startproject``. Running ``wagtail start mysite`` in
  10. your project will generate a new ``mysite`` folder with a few
  11. Wagtail-specific extras, including the required project settings, a
  12. "home" app with a blank ``HomePage`` model and basic templates and a sample
  13. "search" app.
  14. 3. Install project dependencies::
  15. pip install -r requirements.txt
  16. This ensures that you have the relevant version of Django for the project you've just created.
  17. 4. Create the database::
  18. python manage.py migrate
  19. If you haven't updated the project settings, this will be a SQLite
  20. database file in the project directory.
  21. 5. Create an admin user::
  22. python manage.py createsuperuser
  23. 6. ``python manage.py runserver`` If everything worked,
  24. http://127.0.0.1:8000 will show you a welcome page
  25. .. figure:: ../_static/images/tutorial/tutorial_1.png
  26. :alt: Wagtail welcome message
  27. You can now access the administrative area at ``/admin``
  28. .. figure:: ../_static/images/tutorial/tutorial_2.png
  29. :alt: Administrative screen
  30. Extend the HomePage model
  31. -------------------------
  32. Out of the box, the "home" app defines a blank ``HomePage`` model in ``models.py``, along with a migration that creates a homepage and configures Wagtail to use it.
  33. Edit ``home/models.py`` as follows, to add a ``body`` field to the model:
  34. .. code-block:: python
  35. from __future__ import unicode_literals
  36. from django.db import models
  37. from wagtail.wagtailcore.models import Page
  38. from wagtail.wagtailcore.fields import RichTextField
  39. from wagtail.wagtailadmin.edit_handlers import FieldPanel
  40. class HomePage(Page):
  41. body = RichTextField(blank=True)
  42. content_panels = Page.content_panels + [
  43. FieldPanel('body', classname="full")
  44. ]
  45. ``body`` is defined as ``RichTextField``, a special Wagtail field. You
  46. can use any of the `Django core fields <https://docs.djangoproject.com/en/1.8/ref/models/fields/>`__. ``content_panels`` define the
  47. capabilities and the layout of the editing interface. :doc:`More on creating Page models. <../topics/creating_pages>`
  48. Run ``python manage.py makemigrations``, then
  49. ``python manage.py migrate`` to update the database with your model
  50. changes. You must run the above commands each time you make changes to
  51. the model definition.
  52. You can now edit the homepage within the Wagtail admin area (go to Explorer, Homepage, then Edit) to see the new body field. Enter some text into the body field, and publish the page.
  53. The page template now needs to be updated to reflect the changes made
  54. to the model. Wagtail uses normal Django templates to render each page
  55. type. It automatically generates a template filename from the model name
  56. by separating capital letters with underscores (e.g. HomePage becomes
  57. home\_page.html). Edit
  58. ``home/templates/home/home_page.html`` to contain the following:
  59. .. code-block:: html+django
  60. {% extends "base.html" %}
  61. {% load wagtailcore_tags %}
  62. {% block body_class %}template-homepage{% endblock %}
  63. {% block content %}
  64. {{ self.body|richtext }}
  65. {% endblock %}
  66. .. figure:: ../_static/images/tutorial/tutorial_3.png
  67. :alt: Updated homepage
  68. Wagtail template tags
  69. ~~~~~~~~~~~~~~~~~~~~~
  70. Wagtail provides a number of
  71. `template tags & filters <../topics/writing_templates#template-tags-filters>`__
  72. which can be loaded by including ``{% load wagtailcore_tags %}`` at the top of
  73. your template file.
  74. In this tutorial, we use the `richtext` filter to escape and print the contents
  75. of a ``RichTextField``:
  76. .. code-block:: html+django
  77. {% load wagtailcore_tags %}
  78. {{ self.body|richtext }}
  79. Produces:
  80. .. code-block:: html
  81. <div class="rich-text">
  82. <p>
  83. <b>Welcome</b> to our new site!
  84. </p>
  85. </div>
  86. **Note:** You'll need to include ``{% load wagtailcore_tags %}`` in each
  87. template that uses Wagtail's tags. Django will throw a ``TemplateSyntaxError``
  88. if the tags aren't loaded.
  89. A basic blog
  90. ------------
  91. We are now ready to create a blog. To do so, run
  92. ``python manage.py startapp blog`` to create a new app in your Wagtail site.
  93. Add the new ``blog`` app to ``INSTALLED_APPS`` in ``mysite/settings/base.py``.
  94. The following example defines a basic blog post model in ``blog/models.py``:
  95. .. code-block:: python
  96. from django.db import models
  97. from wagtail.wagtailcore.models import Page
  98. from wagtail.wagtailcore.fields import RichTextField
  99. from wagtail.wagtailadmin.edit_handlers import FieldPanel
  100. from wagtail.wagtailsearch import index
  101. class BlogPage(Page):
  102. date = models.DateField("Post date")
  103. intro = models.CharField(max_length=250)
  104. body = RichTextField(blank=True)
  105. search_fields = Page.search_fields + (
  106. index.SearchField('intro'),
  107. index.SearchField('body'),
  108. )
  109. content_panels = Page.content_panels + [
  110. FieldPanel('date'),
  111. FieldPanel('intro'),
  112. FieldPanel('body', classname="full")
  113. ]
  114. Create a template at ``blog/templates/blog/blog_page.html``:
  115. .. code-block:: html+django
  116. {% extends "base.html" %}
  117. {% load wagtailcore_tags %}
  118. {% block body_class %}template-blogpage{% endblock %}
  119. {% block content %}
  120. <h1>{{ self.title }}</h1>
  121. <p class="meta">{{ self.date }}</p>
  122. <div class="intro">{{ self.intro }}</div>
  123. {{ self.body|richtext }}
  124. {% endblock %}
  125. Run ``python manage.py makemigrations`` and ``python manage.py migrate``.
  126. .. figure:: ../_static/images/tutorial/tutorial_4.png
  127. :alt: Create page screen
  128. .. figure:: ../_static/images/tutorial/tutorial_5.png
  129. :alt: Page edit screen
  130. Image support
  131. ~~~~~~~~~~~~~
  132. Wagtail provides support for images out of the box. To add them to your
  133. model:
  134. .. code-block:: python
  135. from django.db import models
  136. from wagtail.wagtailcore.models import Page
  137. from wagtail.wagtailcore.fields import RichTextField
  138. from wagtail.wagtailadmin.edit_handlers import FieldPanel
  139. from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
  140. from wagtail.wagtailsearch import index
  141. class BlogPage(Page):
  142. main_image = models.ForeignKey(
  143. 'wagtailimages.Image',
  144. null=True,
  145. blank=True,
  146. on_delete=models.SET_NULL,
  147. related_name='+'
  148. )
  149. date = models.DateField("Post date")
  150. intro = models.CharField(max_length=250)
  151. body = RichTextField(blank=True)
  152. search_fields = Page.search_fields + (
  153. index.SearchField('intro'),
  154. index.SearchField('body'),
  155. )
  156. content_panels = Page.content_panels + [
  157. FieldPanel('date'),
  158. ImageChooserPanel('main_image'),
  159. FieldPanel('intro'),
  160. FieldPanel('body'),
  161. ]
  162. Run ``python manage.py makemigrations`` and ``python manage.py migrate``.
  163. Adjust your blog page template to include the image:
  164. .. code-block:: html+django
  165. {% extends "base.html" %}
  166. {% load wagtailcore_tags wagtailimages_tags %}
  167. {% block body_class %}template-blogpage{% endblock %}
  168. {% block content %}
  169. <h1>{{ self.title }}</h1>
  170. <p class="meta">{{ self.date }}</p>
  171. {% if self.main_image %}
  172. {% image self.main_image width-400 %}
  173. {% endif %}
  174. <div class="intro">{{ self.intro }}</div>
  175. {{ self.body|richtext }}
  176. {% endblock %}
  177. .. figure:: ../_static/images/tutorial/tutorial_6.png
  178. :alt: A blog post sample
  179. You can read more about using images in templates in the
  180. :doc:`docs <../topics/images/index>`.
  181. Blog Index
  182. ~~~~~~~~~~
  183. Let us extend the Blog app to provide an index.
  184. .. code-block:: python
  185. class BlogIndexPage(Page):
  186. intro = RichTextField(blank=True)
  187. content_panels = Page.content_panels + [
  188. FieldPanel('intro', classname="full")
  189. ]
  190. The above creates an index type to collect all our blog posts.
  191. ``blog/templates/blog/blog_index_page.html``
  192. .. code-block:: html+django
  193. {% extends "base.html" %}
  194. {% load wagtailcore_tags %}
  195. {% block body_class %}template-blogindexpage{% endblock %}
  196. {% block content %}
  197. <h1>{{ self.title }}</h1>
  198. <div class="intro">{{ self.intro|richtext }}</div>
  199. {% endblock %}
  200. Related items
  201. ~~~~~~~~~~~~~
  202. Let's extend the BlogIndexPage to add related links. The related links
  203. can be BlogPages or external links. Change ``blog/models.py`` to
  204. .. code-block:: python
  205. from django.db import models
  206. from modelcluster.fields import ParentalKey
  207. from wagtail.wagtailcore.models import Page, Orderable
  208. from wagtail.wagtailcore.fields import RichTextField
  209. from wagtail.wagtailadmin.edit_handlers import (FieldPanel,
  210. InlinePanel,
  211. MultiFieldPanel,
  212. PageChooserPanel)
  213. from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
  214. from wagtail.wagtailsearch import index
  215. # ...
  216. class LinkFields(models.Model):
  217. link_external = models.URLField("External link", blank=True)
  218. link_page = models.ForeignKey(
  219. 'wagtailcore.Page',
  220. null=True,
  221. blank=True,
  222. related_name='+'
  223. )
  224. @property
  225. def link(self):
  226. if self.link_page:
  227. return self.link_page.url
  228. else:
  229. return self.link_external
  230. panels = [
  231. FieldPanel('link_external'),
  232. PageChooserPanel('link_page'),
  233. ]
  234. class Meta:
  235. abstract = True
  236. # Related links
  237. class RelatedLink(LinkFields):
  238. title = models.CharField(max_length=255, help_text="Link title")
  239. panels = [
  240. FieldPanel('title'),
  241. MultiFieldPanel(LinkFields.panels, "Link"),
  242. ]
  243. class Meta:
  244. abstract = True
  245. class BlogIndexRelatedLink(Orderable, RelatedLink):
  246. page = ParentalKey('BlogIndexPage', related_name='related_links')
  247. class BlogIndexPage(Page):
  248. intro = RichTextField(blank=True)
  249. content_panels = Page.content_panels + [
  250. FieldPanel('intro', classname="full"),
  251. InlinePanel('related_links', label="Related links"),
  252. ]
  253. .. figure:: ../_static/images/tutorial/tutorial_7.png
  254. :alt: Blog index edit screen
  255. Extend ``blog_index_page.html`` to show related items
  256. .. code-block:: html+django
  257. {% extends "base.html" %}
  258. {% load wagtailcore_tags %}
  259. {% block body_class %}template-blogindexpage{% endblock %}
  260. {% block content %}
  261. <h1>{{ self.title }}</h1>
  262. <div class="intro">{{ self.intro|richtext }}</div>
  263. {% if self.related_links.all %}
  264. <ul>
  265. {% for item in self.related_links.all %}
  266. <li><a href="{{ item.link }}">{{ item.title }}</a></li>
  267. {% endfor %}
  268. </ul>
  269. {% endif %}
  270. {% endblock %}
  271. You now have a fully working blog with featured blog posts.
  272. .. figure:: ../_static/images/tutorial/tutorial_8.png
  273. :alt: Barebones blog index
  274. Where next
  275. ----------
  276. - Read the Wagtail :doc:`topics <../topics/index>` and :doc:`reference <../reference/index>` documentation
  277. - Learn how to implement :doc:`StreamField <../topics/streamfield>` for freeform page content
  278. - Browse through the :doc:`advanced topics <../advanced_topics/index>` section and read :doc:`third-party tutorials <../advanced_topics/third_party_tutorials>`