kopia lustrzana https://github.com/wagtail/wagtail
Merge branch 'master' into pr/539
commit
c5ae725401
|
@ -5,6 +5,7 @@ branch = True
|
|||
source = wagtail
|
||||
|
||||
omit =
|
||||
*/south_migrations/*
|
||||
*/migrations/*
|
||||
wagtail/vendor/*
|
||||
|
||||
|
@ -31,4 +32,4 @@ exclude_lines =
|
|||
ignore_errors = True
|
||||
|
||||
[html]
|
||||
directory = coverage_html_report
|
||||
directory = coverage_html_report
|
||||
|
|
31
.travis.yml
31
.travis.yml
|
@ -1,29 +1,38 @@
|
|||
language: python
|
||||
# Test matrix
|
||||
python:
|
||||
- 2.7
|
||||
- 3.2
|
||||
- 3.4
|
||||
env:
|
||||
- DJANGO_VERSION=Django==1.6.5
|
||||
#- DJANGO_VERSION=Django==1.7.0
|
||||
# - TOXENV=py26-dj16-postgres
|
||||
- TOXENV=py26-dj16-sqlite
|
||||
- TOXENV=py27-dj16-postgres
|
||||
# - TOXENV=py27-dj16-sqlite
|
||||
- TOXENV=py32-dj16-postgres
|
||||
# - TOXENV=py33-dj16-postgres
|
||||
- TOXENV=py34-dj16-postgres
|
||||
- TOXENV=py27-dj17-postgres
|
||||
# - TOXENV=py27-dj17-sqlite
|
||||
# - TOXENV=py32-dj17-postgres
|
||||
# - TOXENV=py33-dj17-postgres
|
||||
- TOXENV=py34-dj17-postgres
|
||||
|
||||
# Services
|
||||
services:
|
||||
- redis-server
|
||||
- elasticsearch
|
||||
|
||||
# Package installation
|
||||
install:
|
||||
- python setup.py install
|
||||
- pip install psycopg2 elasticsearch wand embedly mock python-dateutil
|
||||
- pip install coveralls
|
||||
- pip install tox coveralls
|
||||
|
||||
# Pre-test configuration
|
||||
before_script:
|
||||
- psql -c 'create database wagtaildemo;' -U postgres
|
||||
|
||||
# Run the tests
|
||||
script:
|
||||
coverage run runtests.py
|
||||
tox
|
||||
|
||||
after_success:
|
||||
coveralls
|
||||
|
||||
# Who to notify about build results
|
||||
notifications:
|
||||
email:
|
||||
|
|
|
@ -53,4 +53,10 @@ type = PO
|
|||
file_filter = wagtail/wagtailusers/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = wagtail/wagtailusers/locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
type = PO
|
||||
|
||||
[wagtail.wagtailforms]
|
||||
file_filter = wagtail/wagtailforms/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = wagtail/wagtailforms/locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
|
|
@ -1,6 +1,32 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
0.7 (xx.xx.2014)
|
||||
~~~~~~~~~~~~~~~~
|
||||
* Added interface for choosing focal point on images
|
||||
* Removed 'content_type' template filter from the project template, as the same thing can be accomplished with self.get_verbose_name|slugify
|
||||
* Page copy operations now also copy the page revision history
|
||||
* Page models now support a 'parent_page_types' property in addition to 'subpage types', to restrict the types of page they can be created under
|
||||
* 'register_snippet' can now be invoked as a decorator
|
||||
|
||||
0.6 (11.09.2014)
|
||||
~~~~~~~~~~~~~~~~
|
||||
* Added 'wagtail start' command and project template
|
||||
* Added Django 1.7 support
|
||||
* Added {% routablepageurl %} template tag (Tim Heap)
|
||||
* Added RoutablePageMixin (Tim Heap)
|
||||
* MenuItems can now have bundled JavaScript
|
||||
* Added the register_admin_menu_item hook for registering menu items at startup
|
||||
* Added version indicator to the admin interface
|
||||
* Renamed wagtailsearch.indexed to wagtailsearch.index
|
||||
* Added Russian translation
|
||||
* Fix: Page URL generation now returns correct URLs for sites that have the main 'serve' view rooted somewhere other than '/' (Nathan Brizendine)
|
||||
* Fix: Search results in the page chooser now respect the page_type parameter on PageChooserPanel
|
||||
* Fix: Rendition filenames are now prevented from going over 60 chars, even with a large focal_point_key
|
||||
* Fix: Child relations that are defined on a model's superclass (such as the base Page model) are now picked up correctly by the page editing form, page copy operations and the replace_text management command
|
||||
* Fix: (For Django 1.7 support) Do not import South when using Django 1.7 (thenewguy)
|
||||
* Fix: Tags on images and documents are now committed to the search index immediately on saving
|
||||
|
||||
0.5 (01.08.2014)
|
||||
~~~~~~~~~~~~~~~~
|
||||
* Added multiple image uploader
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Original Authors
|
||||
Authors
|
||||
================
|
||||
|
||||
* Matthew Westcott matthew.westcott@torchbox.com twitter: @gasmanic
|
||||
* David Cranwell david.cranwell@torchbox.com twitter: @davecranwell
|
||||
* Karl Hobley karl.hobley@torchbox.com
|
||||
* Helen Chapman helen.chapman@torchbox.com
|
||||
|
||||
Contributors
|
||||
============
|
||||
|
||||
* Helen Chapman helen.chapman@torchbox.com
|
||||
* Balazs Endresz balazs.endresz@torchbox.com
|
||||
* Neal Todd neal.todd@torchbox.com
|
||||
* Paul Hallett (twilio) hello@phalt.co
|
||||
|
@ -30,6 +30,8 @@ Contributors
|
|||
* Jeffrey Hearn
|
||||
* Robert Clark
|
||||
* Tim Heap
|
||||
* Nathan Brizendine
|
||||
* thenewguy
|
||||
|
||||
Translators
|
||||
===========
|
||||
|
@ -44,7 +46,9 @@ Translators
|
|||
* Greek: Serafeim Papastefanos
|
||||
* Mongolian: Delgermurun Purevkhuu
|
||||
* Polish: Łukasz Bołdys
|
||||
* Portuguese: Jose Lourenco
|
||||
* Portuguese Brazil: Gilson Filho
|
||||
* Romanian: Dan Braghis
|
||||
* Russian: ice9, HNKNTA
|
||||
* Spanish: Unai Zalakain, fooflare
|
||||
* Traditional Chinese (Taiwan): wdv4758h
|
||||
|
|
21
README.rst
21
README.rst
|
@ -24,18 +24,25 @@ Wagtail is a Django content management system built originally for the `Royal Co
|
|||
* Support for tree-based content organisation
|
||||
* Optional preview->submit->approve workflow
|
||||
* Fast out of the box. `Varnish <https://www.varnish-cache.org/>`_-friendly if you need it
|
||||
* A simple `form builder <http://docs.wagtail.io/en/latest/form_builder.html>`_
|
||||
* Optional `static site generation <http://docs.wagtail.io/en/latest/static_site_generation.html>`_
|
||||
* A simple `form builder <http://docs.wagtail.io/en/latest/core_components/form_builder.html>`_
|
||||
* Optional `static site generation <http://docs.wagtail.io/en/latest/contrib_components/static_site_generation.html>`_
|
||||
* Excellent `test coverage <https://coveralls.io/r/torchbox/wagtail?branch=master>`_
|
||||
|
||||
Find out more at `wagtail.io <http://wagtail.io/>`_.
|
||||
|
||||
Got a question? Ask it on our `Google Group <https://groups.google.com/forum/#!forum/wagtail>`_.
|
||||
|
||||
Who's using it?
|
||||
~~~~~~~~~~~~~~~
|
||||
We've a list of public Wagtail sites here: https://github.com/torchbox/wagtail/wiki/Public-Wagtail-sites
|
||||
|
||||
Got one of your own? Feel free to add it!
|
||||
|
||||
|
||||
Getting started
|
||||
~~~~~~~~~~~~~~~
|
||||
* To get you up and running quickly, we've provided a demonstration site with all the configuration in place, at `github.com/torchbox/wagtaildemo <https://github.com/torchbox/wagtaildemo/>`_; see the `README <https://github.com/torchbox/wagtaildemo/blob/master/README.md>`_ for installation instructions.
|
||||
* See the `Getting Started <http://wagtail.readthedocs.org/en/latest/gettingstarted.html#getting-started>`_ docs for installation (with the demo app) on a fresh Debian/Ubuntu box with production-ready dependencies, on OS X and on a Vagrant box.
|
||||
* See the `Getting Started <http://wagtail.readthedocs.org/en/latest/getting_started/installation.html>`_ docs for installation (with the demo app) on a fresh Debian/Ubuntu box with production-ready dependencies, on OS X and on a Vagrant box.
|
||||
* `Serafeim Papastefanos <https://github.com/spapas>`_ has written a `tutorial <http://spapas.github.io/2014/02/13/wagtail-tutorial/>`_ with all the steps to build a simple Wagtail site from scratch.
|
||||
* We've also provided a skeletal django-template to get started on a blank site: https://github.com/torchbox/wagtail-template
|
||||
|
||||
|
@ -45,9 +52,7 @@ Available at `wagtail.readthedocs.org <http://wagtail.readthedocs.org/>`_ and al
|
|||
|
||||
Compatibility
|
||||
~~~~~~~~~~~~~
|
||||
Wagtail supports Django 1.6.2+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4.
|
||||
|
||||
Django 1.7 support is in progress pending further release candidate testing.
|
||||
Wagtail supports Django 1.6.2+ and 1.7.0+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4.
|
||||
|
||||
Wagtail's dependencies are summarised at `requirements.io <https://requires.io/github/torchbox/wagtail/requirements>`_.
|
||||
|
||||
|
@ -55,8 +60,8 @@ Contributing
|
|||
~~~~~~~~~~~~
|
||||
If you're a Python or Django developer, fork the repo and get stuck in!
|
||||
|
||||
We suggest you start by checking the `Help develop me! <https://github.com/torchbox/wagtail/issues?labels=Help+develop+me%21>`_ label and the `coding guidelines <http://wagtail.readthedocs.org/en/latest/contributing.html#coding-guidelines>`_.
|
||||
We suggest you start by checking the `Help develop me! <https://github.com/torchbox/wagtail/issues?labels=Help+develop+me%21>`_ label and the `coding guidelines <http://wagtail.readthedocs.org/en/latest/howto/contributing.html#coding-guidelines>`_.
|
||||
|
||||
Send us a useful pull request and we'll post you a `t-shirt <https://twitter.com/WagtailCMS/status/432166799464210432/photo/1>`_.
|
||||
|
||||
We also welcome `translations <http://wagtail.readthedocs.org/en/latest/contributing.html#translations>`_ for Wagtail's interface.
|
||||
We also welcome `translations <http://wagtail.readthedocs.org/en/latest/howto/contributing.html#translations>`_ for Wagtail's interface.
|
||||
|
|
|
@ -29,6 +29,9 @@ if not on_rtd: # only import and set the theme if we're building docs locally
|
|||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
# Get Wagtail version
|
||||
from wagtail.wagtailcore import __version__
|
||||
|
||||
# Autodoc may need to import some models modules which require django settings
|
||||
# be configured
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'wagtail.tests.settings'
|
||||
|
@ -70,9 +73,9 @@ copyright = u'2014, Torchbox'
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.5'
|
||||
version = __version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.5'
|
||||
release = __version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -71,7 +71,7 @@ Using the URLs on your website or blog
|
|||
|
||||
Once you have generated a URL, you can put it straight into the ``src`` attribute of an ``<img>`` tag:
|
||||
|
||||
..code-block:: html
|
||||
.. code-block:: html
|
||||
|
||||
<img src="(image url here)">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Core components
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
sites
|
||||
pages/index
|
||||
images/index
|
||||
snippets
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
.. _routable_page:
|
||||
|
||||
====================================
|
||||
Embedding URL configuration in Pages
|
||||
====================================
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
The ``RoutablePage`` class provides a convenient way for a page to respond on multiple sub-URLs with different views. For example, a blog section on a site might provide several different types of index page at URLs like ``/blog/2013/06/``, ``/blog/authors/bob/``, ``/blog/tagged/python/``, all served by the same ``BlogIndex`` page.
|
||||
|
||||
A ``RoutablePage`` exists within the page tree like any other page, but URL paths underneath it are checked against a list of patterns, using Django's urlconf scheme. If none of the patterns match, control is passed to subpages as usual (or failing that, a 404 error is thrown).
|
||||
|
||||
|
||||
The basics
|
||||
==========
|
||||
|
||||
To use ``RoutablePage``, you need to make your class inherit from :class:`wagtail.contrib.wagtailroutablepage.models.RoutablePage` and configure the ``subpage_urls`` attribute with your URL configuration.
|
||||
|
||||
Here's an example of an ``EventPage`` with three views:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
|
||||
|
||||
|
||||
class EventPage(RoutablePage):
|
||||
subpage_urls = (
|
||||
url(r'^$', 'current_events', name='current_events'),
|
||||
url(r'^past/$', 'past_events', name='past_events'),
|
||||
url(r'^year/(\d+)/$', 'events_for_year', name='events_for_year'),
|
||||
)
|
||||
|
||||
def current_events(self, request):
|
||||
"""
|
||||
View function for the current events page
|
||||
"""
|
||||
...
|
||||
|
||||
def past_events(self, request):
|
||||
"""
|
||||
View function for the current events page
|
||||
"""
|
||||
...
|
||||
|
||||
def events_for_year(self, request):
|
||||
"""
|
||||
View function for the events for year page
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
The ``RoutablePage`` class
|
||||
==========================
|
||||
|
||||
.. automodule:: wagtail.contrib.wagtailroutablepage.models
|
||||
.. autoclass:: RoutablePage
|
||||
|
||||
.. autoattribute:: subpage_urls
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
subpage_urls = (
|
||||
url(r'^$', 'serve', name='main'),
|
||||
url(r'^archive/$', 'archive', name='archive'),
|
||||
)
|
||||
|
||||
.. automethod:: resolve_subpage
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
view, args, kwargs = page.resolve_subpage('/past/')
|
||||
response = view(request, *args, **kwargs)
|
||||
|
||||
.. automethod:: reverse_subpage
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url = page.url + page.reverse_subpage('events_for_year', args=('2014', ))
|
|
@ -0,0 +1,119 @@
|
|||
.. _routable_page_mixin:
|
||||
|
||||
====================================
|
||||
Embedding URL configuration in Pages
|
||||
====================================
|
||||
|
||||
.. versionadded:: 0.6
|
||||
|
||||
The ``RoutablePageMixin`` mixin provides a convenient way for a page to respond on multiple sub-URLs with different views. For example, a blog section on a site might provide several different types of index page at URLs like ``/blog/2013/06/``, ``/blog/authors/bob/``, ``/blog/tagged/python/``, all served by the same ``BlogIndex`` page.
|
||||
|
||||
A ``Page`` using ``RoutablePageMixin`` exists within the page tree like any other page, but URL paths underneath it are checked against a list of patterns, using Django's urlconf scheme. If none of the patterns match, control is passed to subpages as usual (or failing that, a 404 error is thrown).
|
||||
|
||||
|
||||
The basics
|
||||
==========
|
||||
|
||||
To use ``RoutablePageMixin``, you need to make your class inherit from both :class:`wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin` and :class:`wagtail.wagtailcore.models.Page`, and configure the ``subpage_urls`` attribute with your URL configuration.
|
||||
|
||||
Here's an example of an ``EventPage`` with three views:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
class EventPage(RoutablePageMixin, Page):
|
||||
subpage_urls = (
|
||||
url(r'^$', 'current_events', name='current_events'),
|
||||
url(r'^past/$', 'past_events', name='past_events'),
|
||||
url(r'^year/(\d+)/$', 'events_for_year', name='events_for_year'),
|
||||
)
|
||||
|
||||
def current_events(self, request):
|
||||
"""
|
||||
View function for the current events page
|
||||
"""
|
||||
...
|
||||
|
||||
def past_events(self, request):
|
||||
"""
|
||||
View function for the past events page
|
||||
"""
|
||||
...
|
||||
|
||||
def events_for_year(self, request):
|
||||
"""
|
||||
View function for the events for year page
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
The ``RoutablePageMixin`` class
|
||||
===============================
|
||||
|
||||
.. automodule:: wagtail.contrib.wagtailroutablepage.models
|
||||
.. autoclass:: RoutablePageMixin
|
||||
|
||||
.. autoattribute:: subpage_urls
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
class MyPage(RoutablePageMixin, Page):
|
||||
subpage_urls = (
|
||||
url(r'^$', 'main', name='main'),
|
||||
url(r'^archive/$', 'archive', name='archive'),
|
||||
url(r'^archive/(?P<year>[0-9]{4})/$', 'archive', name='archive'),
|
||||
)
|
||||
|
||||
def main(self, request):
|
||||
...
|
||||
|
||||
def archive(self, request, year=None):
|
||||
...
|
||||
|
||||
.. automethod:: resolve_subpage
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
view, args, kwargs = page.resolve_subpage('/archive/')
|
||||
response = view(request, *args, **kwargs)
|
||||
|
||||
.. automethod:: reverse_subpage
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url = page.url + page.reverse_subpage('archive', kwargs={'year': '2014'})
|
||||
|
||||
|
||||
.. _routablepageurl_template_tag:
|
||||
|
||||
The ``routablepageurl`` template tag
|
||||
====================================
|
||||
|
||||
.. currentmodule:: wagtail.contrib.wagtailroutablepage.templatetags.wagtailroutablepage_tags
|
||||
.. autofunction:: routablepageurl
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load wagtailroutablepage_tags %}
|
||||
|
||||
{% routablepageurl self "feed" %}
|
||||
{% routablepageurl self "archive" 2014 08 14 %}
|
||||
{% routablepageurl self "food" foo="bar" baz="quux" %}
|
|
@ -2,40 +2,15 @@
|
|||
Creating page models
|
||||
====================
|
||||
|
||||
Wagtail provides a ``Page`` class to represent types of page (a.k.a Content types). Developers should subclass ``Page`` for their own page models.
|
||||
|
||||
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``.
|
||||
``Page`` uses Django's model interface, so you can include any field type and field options that Django allows. Wagtail provides some field types of its own which simplify data entry in the Wagtail admin interface. Wagtail also wraps Django's field types and widgets with its own concept of "Edit Handlers" and "Panels". These further improve the data entry experience.
|
||||
|
||||
|
||||
Built-in Properties of the Page Class
|
||||
-------------------------------------
|
||||
An example Wagtail Page Model
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
`````````````````
|
||||
|
||||
``title`` (string, required)
|
||||
Human-readable title for the content
|
||||
|
||||
``slug`` (string, required)
|
||||
Machine-readable URL component for this piece of content. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/``
|
||||
|
||||
``seo_title`` (string)
|
||||
Alternate SEO-crafted title which overrides the normal title for use in the ``<head>`` of a page
|
||||
|
||||
``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
|
||||
|
||||
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? Here's a model representing a typical blog post:
|
||||
This example represents a typical blog post:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -58,6 +33,8 @@ So what does a Wagtail model definition look like? Here's a model representing a
|
|||
related_name='+'
|
||||
)
|
||||
|
||||
|
||||
|
||||
BlogPage.content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
FieldPanel('date'),
|
||||
|
@ -72,17 +49,48 @@ So what does a Wagtail model definition look like? Here's a model representing a
|
|||
ImageChooserPanel('feed_image'),
|
||||
]
|
||||
|
||||
To keep track of your ``Page``-derived models, it might be helpful to include "Page" as the last part of your class name. ``BlogPage`` defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``).
|
||||
.. tip::
|
||||
To keep track of ``Page`` models and avoid class name clashes, it can be helpful to suffix model class names with "Page" e.g BlogPage, ListingIndexPage.
|
||||
|
||||
Next, the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the Wagtail admin page edit interface. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images, and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises.
|
||||
In the example above the ``BlogPage`` class defines three properties: ``body``, ``date``, and ``feed_image``. These are a mix of basic Django models (``DateField``), Wagtail fields (``RichTextField``), and a pointer to a Wagtail model (``Image``).
|
||||
|
||||
Below that the ``content_panels`` and ``promote_panels`` lists define the capabilities and layout of the page editing interface in the Wagtail admin. The lists are filled with "panels" and "choosers", which will provide a fine-grain interface for inputting the model's content. The ``ImageChooserPanel``, for instance, lets one browse the image library, upload new images and input image metadata. The ``RichTextField`` is the basic field for creating web-ready website rich text, including text formatting and embedded media like images and video. The Wagtail admin offers other choices for fields, Panels, and Choosers, with the option of creating your own to precisely fit your content without workarounds or other compromises.
|
||||
|
||||
Your models may be even more complex, with methods overriding the built-in functionality of the ``Page`` to achieve webdev magic. Or, you can keep your models simple and let Wagtail's built-in functionality do the work.
|
||||
|
||||
Now that we have a basic idea of how our content is defined, lets look at relationships between pieces of content.
|
||||
|
||||
``Page`` Class Reference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Default fields
|
||||
--------------
|
||||
|
||||
Wagtail provides some fields for the ``Page`` class by default, which will be common to all your pages. You don't need to add these fields to your own page models however you do need to allocate them to ``content_panels``, ``promote_panels`` or ``settings_panels``. See above example and for further information on the panels see :ref:`editing-api`.
|
||||
|
||||
``title`` (string, required)
|
||||
Human-readable title of the page - what you'd probably use as your ``<h1>`` tag.
|
||||
|
||||
``slug`` (string, required)
|
||||
Machine-readable URL component for this page. The name of the page as it will appear in URLs e.g ``http://domain.com/blog/[my-slug]/``
|
||||
|
||||
``seo_title`` (string)
|
||||
Alternate SEO-crafted title, mainly for use in the page ``<title>`` tag.
|
||||
|
||||
``search_description`` (string)
|
||||
SEO-crafted description of the content, used for internal search indexing, suitable for your page's ``<meta name="description">`` tag.
|
||||
|
||||
``show_in_menus`` (boolean)
|
||||
Toggles whether the page should be considered for inclusion in any site-wide menus you create.
|
||||
|
||||
``go_live_at`` (datetime)
|
||||
A datetime on which the page should be automatically made published (made publicly accessible)
|
||||
|
||||
``expire_at`` (datetime)
|
||||
A datetime on which the page should be unpublished, rendering it inaccessible to the public.
|
||||
|
||||
|
||||
Page Properties and Methods Reference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Page Attributes, Properties and Methods Reference
|
||||
-------------------------------------------------
|
||||
|
||||
In addition to the model fields provided, ``Page`` has many properties and methods that you may wish to reference, use, or override in creating your own models. Those listed here are relatively straightforward to use, but consult the Wagtail source code for a full view of what's possible.
|
||||
|
||||
|
@ -96,6 +104,8 @@ In addition to the model fields provided, ``Page`` has many properties and metho
|
|||
.. autoattribute:: url
|
||||
|
||||
.. autoattribute:: full_url
|
||||
|
||||
.. automethod:: get_verbose_name
|
||||
|
||||
.. automethod:: relative_url
|
||||
|
||||
|
@ -121,14 +131,68 @@ In addition to the model fields provided, ``Page`` has many properties and metho
|
|||
|
||||
.. automethod:: search
|
||||
|
||||
.. attribute:: search_fields
|
||||
|
||||
A list of fields to be indexed by the search engine. See Search docs :ref:`wagtailsearch_for_python_developers`
|
||||
|
||||
.. _wagtail_site_admin:
|
||||
.. attribute:: subpage_types
|
||||
|
||||
Site
|
||||
A whitelist of page models which can be created as children of this page type e.g a ``BlogIndex`` page might allow ``BlogPage``, but not ``JobPage`` e.g
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class BlogIndex(Page):
|
||||
subpage_types = ['mysite.BlogPage', 'mysite.BlogArchivePage']
|
||||
|
||||
.. attribute:: password_required_template
|
||||
|
||||
Defines which template file should be used to render the login form for Protected pages using this model. This overrides the default, defined using ``PASSWORD_REQUIRED_TEMPLATE`` in your settings. See :ref:`private_pages`
|
||||
|
||||
|
||||
Tips
|
||||
~~~~
|
||||
|
||||
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.
|
||||
Friendly model names
|
||||
--------------------
|
||||
|
||||
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.
|
||||
Make your model names more friendly to users of Wagtail using Django's internal ``Meta`` class with a ``verbose_name`` e.g
|
||||
|
||||
Wagtail's developers plan to move the site settings into the Wagtail admin interface.
|
||||
.. code-block:: python
|
||||
|
||||
class HomePage(Page):
|
||||
...
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Homepage"
|
||||
|
||||
When users are given a choice of pages to create, the list of page types is generated by splitting your model names on each of their capital letters. Thus a ``HomePage`` model would be named "Home Page" which is a little clumsy. ``verbose_name`` as in the example above, would change this to read "Homepage" which is slightly more conventional.
|
||||
|
||||
The above example also ensures the name of the
|
||||
|
||||
Helpful model descriptions
|
||||
--------------------------
|
||||
|
||||
As your site becomes more complex users may require some prompting in deciding which content type to use when creating a new page. Developers can add a description to their Models by extending Django's internal model ``Meta`` class.
|
||||
|
||||
Insert the following once at the top of your ``models.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import django.db.models.options as options
|
||||
options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('description',)
|
||||
|
||||
|
||||
Then for each model as necessary, add a description option to the model ``Meta`` class
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class HomePage(Page):
|
||||
...
|
||||
|
||||
class Meta:
|
||||
description = "The top level homepage for your site"
|
||||
verbose_name = "Homepage"
|
||||
|
||||
|
||||
(This method can be used to extend the Model Meta class in various ways however Wagtail only supports the addition of a ``description`` option).
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.. _editing-api:
|
||||
|
||||
Defining models with the Editing API
|
||||
====================================
|
||||
Displaying fields with the Editing API
|
||||
======================================
|
||||
|
||||
.. note::
|
||||
This documentation is currently being written.
|
||||
|
@ -387,6 +388,8 @@ For information on developing custom hallo.js plugins, see the project's page: h
|
|||
Edit Handler API
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. _admin_hooks:
|
||||
|
||||
Admin Hooks
|
||||
-----------
|
||||
|
||||
|
|
|
@ -21,4 +21,4 @@ The presentation of your content, the actual webpages, includes the normal use o
|
|||
editing_api
|
||||
advanced_topics/queryset_methods
|
||||
advanced_topics/private_pages
|
||||
advanced_topics/routable_page
|
||||
advanced_topics/routable_page_mixin
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _pages-theory:
|
||||
|
||||
======
|
||||
Theory
|
||||
======
|
||||
|
@ -50,7 +52,7 @@ A Parent node could provide its own function returning its descendant objects.
|
|||
|
||||
return events
|
||||
|
||||
This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live()``) and are children of this node (``descendant_of(self)``). By setting a ``subpage_types`` class property in your model, you can specify which models are allowed to be set as children, but Wagtail will allow any ``Page``-derived model by default. Regardless, it's smart for a parent model to provide an index filtered to make sense.
|
||||
This example makes sure to limit the returned objects to pieces of content which make sense, specifically ones which have been published through Wagtail's admin interface (``live()``) and are children of this node (``descendant_of(self)``). By setting a ``subpage_types`` class property in your model, you can specify which models are allowed to be set as children, and by setting a ``parent_page_types`` class property, you can specify which models are allowed to be parents of this page model. Wagtail will allow any ``Page``-derived model by default. Regardless, it's smart for a parent model to provide an index filtered to make sense.
|
||||
|
||||
|
||||
Leaves
|
||||
|
@ -69,7 +71,7 @@ The model for the leaf could provide a function that traverses the tree in the o
|
|||
# Find closest ancestor which is an event index
|
||||
return self.get_ancestors().type(EventIndexPage).last()
|
||||
|
||||
If defined, ``subpage_types`` will also limit the parent models allowed to contain a leaf. If not, Wagtail will allow any combination of parents and leafs to be associated in the Wagtail tree. Like with index pages, it's a good idea to make sure that the index is actually of the expected model to contain the leaf.
|
||||
If defined, ``subpage_types`` and ``parent_page_types`` will also limit the parent models allowed to contain a leaf. If not, Wagtail will allow any combination of parents and leafs to be associated in the Wagtail tree. Like with index pages, it's a good idea to make sure that the index is actually of the expected model to contain the leaf.
|
||||
|
||||
|
||||
Other Relationships
|
||||
|
|
|
@ -112,13 +112,16 @@ For example:
|
|||
<!-- or a square thumbnail: -->
|
||||
{% image self.photo fill-80x80 %}
|
||||
|
||||
In the above syntax ``[image]`` is the Django object refering to the image. If your page model defined a field called "photo" then ``[image]`` would probably be ``self.photo``. The ``[resize-rule]`` defines how the image is to be resized when inserted into the page; various resizing methods are supported, to cater for different usage cases (e.g. lead images that span the whole width of the page, or thumbnails to be cropped to a fixed size).
|
||||
In the above syntax example ``[image]`` is the Django object refering to the image. If your page model defined a field called "photo" then ``[image]`` would probably be ``self.photo``. The ``[resize-rule]`` defines how the image is to be resized when inserted into the page; various resizing methods are supported, to cater for different usage cases (e.g. lead images that span the whole width of the page, or thumbnails to be cropped to a fixed size).
|
||||
|
||||
Note that a space separates ``[image]`` and ``[resize-rule]``, but the resize rule must not contain spaces.
|
||||
|
||||
|
||||
The available resizing methods are:
|
||||
|
||||
|
||||
.. glossary::
|
||||
|
||||
``max``
|
||||
(takes two dimensions)
|
||||
|
||||
|
@ -182,6 +185,7 @@ The available resizing methods are:
|
|||
Leaves the image at its original size - no resizing is performed.
|
||||
|
||||
|
||||
|
||||
.. Note::
|
||||
Wagtail does not allow deforming or stretching images. Image dimension ratios will always be kept. Wagtail also *does not support upscaling*. Small images forced to appear at larger sizes will "max out" at their their native dimensions.
|
||||
|
||||
|
@ -218,6 +222,15 @@ Wagtail can assign the image data to another variable using Django's ``as`` synt
|
|||
height="{{ tmp_photo.height }}" alt="{{ tmp_photo.alt }}" class="my-custom-class" />
|
||||
|
||||
|
||||
This syntax exposes the underlying image "Rendition" (``tmp_photo``) to the developer. A "Rendition" contains just the information specific to the way you've requested to format the image i.e dimensions and source URL.
|
||||
|
||||
If your site defines a custom image model using ``AbstractImage``, then any additional fields you add to an image e.g a copyright holder, are **not** part of the image *rendition*, they're part of the image *model*.
|
||||
|
||||
Therefore in the above example, if you'd added the field ``foo`` to your AbstractImage you'd access it using ``{{ self.photo.foo }}`` not ``{{ tmp_photo.foo }}``.
|
||||
|
||||
(Due to the links in the database between renditions and their parent image, you could also access it as ``{{ tmp_photo.image.foo }}`` but this is clearly confusing.)
|
||||
|
||||
|
||||
.. Note::
|
||||
The image property used for the ``src`` attribute is actually ``image.url``, not ``image.src``.
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ For Python developers
|
|||
Basic usage
|
||||
===========
|
||||
|
||||
By default using the :ref:`wagtailsearch_backends_database`, Wagtail's search will only index the ``title`` field of pages.
|
||||
|
||||
All searches are performed on Django QuerySets. Wagtail provides a ``search`` method on the queryset for all page models:
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -35,20 +37,20 @@ Indexing extra fields
|
|||
|
||||
The ``indexed_fields`` configuration format was replaced with ``search_fields``
|
||||
|
||||
.. versionchanged:: 0.6
|
||||
|
||||
.. note::
|
||||
|
||||
Searching on extra fields with the database backend is not currently supported.
|
||||
The ``wagtail.wagtailsearch.indexed`` module was renamed to ``wagtail.wagtailsearch.index``
|
||||
|
||||
|
||||
Fields need to be explicitly added to the search configuration in order for you to be able to search/filter on them.
|
||||
.. warning::
|
||||
|
||||
You can add new fields to the search index by overriding the ``search_fields`` property and appending a list of extra ``SearchField``/``FilterField`` objects to it.
|
||||
|
||||
The default value of ``search_fields`` (as set in ``Page``) indexes the ``title`` field as a ``SearchField`` and some other generally useful fields as ``FilterField`` rules.
|
||||
Indexing extra fields is only supported with ElasticSearch as your backend. If you're using the database backend, any other fields you define via ``search_fields`` will be ignored.
|
||||
|
||||
|
||||
Quick example
|
||||
Fields must be explicitly added to the ``search_fields`` property of your ``Page``-derived model, in order for you to be able to search/filter on them. This is done by overriding ``search_fields`` to append a list of extra ``SearchField``/``FilterField`` objects to it.
|
||||
|
||||
|
||||
Example
|
||||
-------------
|
||||
|
||||
This creates an ``EventPage`` model with two fields ``description`` and ``date``. ``description`` is indexed as a ``SearchField`` and ``date`` is indexed as a ``FilterField``
|
||||
|
@ -56,15 +58,15 @@ This creates an ``EventPage`` model with two fields ``description`` and ``date``
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
from wagtail.wagtailsearch import index
|
||||
|
||||
class EventPage(Page):
|
||||
description = models.TextField()
|
||||
date = models.DateField()
|
||||
|
||||
search_fields = Page.search_fields + ( # Inherit search_fields from Page
|
||||
indexed.SearchField('description'),
|
||||
indexed.FilterField('date'),
|
||||
index.SearchField('description'),
|
||||
index.FilterField('date'),
|
||||
)
|
||||
|
||||
|
||||
|
@ -72,7 +74,7 @@ This creates an ``EventPage`` model with two fields ``description`` and ``date``
|
|||
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Christmas")
|
||||
|
||||
|
||||
``indexed.SearchField``
|
||||
``index.SearchField``
|
||||
-----------------------
|
||||
|
||||
These are added to the search index and are used for performing full-text searches on your models. These would usually be text fields.
|
||||
|
@ -86,7 +88,7 @@ Options
|
|||
- **es_extra** (dict) - This field is to allow the developer to set or override any setting on the field in the ElasticSearch mapping. Use this if you want to make use of any ElasticSearch features that are not yet supported in Wagtail.
|
||||
|
||||
|
||||
``indexed.FilterField``
|
||||
``index.FilterField``
|
||||
-----------------------
|
||||
|
||||
These are added to the search index but are not used for full-text searches. Instead, they allow you to run filters on your search results.
|
||||
|
@ -107,7 +109,7 @@ One use for this is indexing ``get_*_display`` methods Django creates automatica
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
from wagtail.wagtailsearch import index
|
||||
|
||||
class EventPage(Page):
|
||||
IS_PRIVATE_CHOICES = (
|
||||
|
@ -119,10 +121,10 @@ One use for this is indexing ``get_*_display`` methods Django creates automatica
|
|||
|
||||
search_fields = Page.search_fields + (
|
||||
# Index the human-readable string for searching
|
||||
indexed.SearchField('get_is_private_display'),
|
||||
index.SearchField('get_is_private_display'),
|
||||
|
||||
# Index the boolean value for filtering
|
||||
indexed.FilterField('is_private'),
|
||||
index.FilterField('is_private'),
|
||||
)
|
||||
|
||||
|
||||
|
@ -131,25 +133,25 @@ Indexing non-page models
|
|||
|
||||
Any Django model can be indexed and searched.
|
||||
|
||||
To do this, inherit from ``indexed.Indexed`` and add some ``search_fields`` to the model.
|
||||
To do this, inherit from ``index.Indexed`` and add some ``search_fields`` to the model.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
from wagtail.wagtailsearch import index
|
||||
|
||||
class Book(models.Model, indexed.Indexed):
|
||||
class Book(models.Model, index.Indexed):
|
||||
title = models.CharField(max_length=255)
|
||||
genre = models.CharField(max_length=255, choices=GENRE_CHOICES)
|
||||
author = models.ForeignKey(Author)
|
||||
published_date = models.DateTimeField()
|
||||
|
||||
search_fields = (
|
||||
indexed.SearchField('title', partial_match=True, boost=10),
|
||||
indexed.SearchField('get_genre_display'),
|
||||
index.SearchField('title', partial_match=True, boost=10),
|
||||
index.SearchField('get_genre_display'),
|
||||
|
||||
indexed.FilterField('genre'),
|
||||
indexed.FilterField('author'),
|
||||
indexed.FilterField('published_date'),
|
||||
index.FilterField('genre'),
|
||||
index.FilterField('author'),
|
||||
index.FilterField('published_date'),
|
||||
)
|
||||
|
||||
# As this model doesn't have a search method in its QuerySet, we have to call search directly on the backend
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.. _wagtail_site_admin:
|
||||
|
||||
Sites
|
||||
=====
|
||||
|
||||
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. See :ref:`pages-theory`.
|
||||
|
||||
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.
|
|
@ -4,7 +4,7 @@
|
|||
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 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 the ``register_snippet`` class decorator.
|
||||
|
||||
Snippets are not search-able or order-able 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.
|
||||
|
||||
|
@ -19,9 +19,10 @@ Here's an example snippet from the Wagtail demo website:
|
|||
|
||||
from wagtail.wagtailadmin.edit_handlers import FieldPanel
|
||||
from wagtail.wagtailsnippets.models import register_snippet
|
||||
|
||||
|
||||
...
|
||||
|
||||
@register_snippet
|
||||
class Advert(models.Model):
|
||||
url = models.URLField(null=True, blank=True)
|
||||
text = models.CharField(max_length=255)
|
||||
|
@ -34,11 +35,9 @@ Here's an example snippet from the Wagtail demo website:
|
|||
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.
|
||||
``@register_snippet`` 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
|
||||
-----------------------------------
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _editor_manual:
|
||||
|
||||
Using Wagtail: an Editor's guide
|
||||
================================
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
=====================
|
||||
Creating your project
|
||||
=====================
|
||||
|
||||
.. contents:: Contents
|
||||
:local:
|
||||
|
||||
|
||||
The ``wagtail start`` command
|
||||
=============================
|
||||
|
||||
The easiest way to start a new project with wagtail is to use the ``wagtail start`` command. This command is installed into your environment when you install Wagtail (see: :doc:`installation`).
|
||||
|
||||
The command works the same way as ``django-admin.py startproject`` except that the produced project is pre-configured for Wagtail. It also contains some useful extras which we will look at in the next section.
|
||||
|
||||
To create a project, cd into a directory where you would like to create your project and run the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wagtail start mysite
|
||||
|
||||
|
||||
The project
|
||||
===========
|
||||
|
||||
Lets look at what ``wagtail start`` created::
|
||||
|
||||
mysite/
|
||||
core/
|
||||
static/
|
||||
templates/
|
||||
base.html
|
||||
404.html
|
||||
500.html
|
||||
mysite/
|
||||
settings/
|
||||
base.py
|
||||
dev.py
|
||||
production.py
|
||||
manage.py
|
||||
vagrant/
|
||||
provision.sh
|
||||
Vagrantfile
|
||||
readme.rst
|
||||
requirements.txt
|
||||
|
||||
|
||||
The "core" app
|
||||
----------------
|
||||
|
||||
Location: ``/mysite/core/``
|
||||
|
||||
This app is here to help get you started quicker by providing a ``HomePage`` model with migrations to create one when you first setup your app.
|
||||
|
||||
|
||||
Default templates and static files
|
||||
----------------------------------
|
||||
|
||||
Location: ``/mysite/core/templates/`` and ``/mysite/core/static/``
|
||||
|
||||
The templates directory contains ``base.html``, ``404.html`` and ``500.html``. These files are very commonly needed on Wagtail sites to they have been added into the template.
|
||||
|
||||
The static directory contains an empty javascript and sass file. Wagtail uses ``django-compressor`` for compiling and compressing static files. For more information, see: `Django Compressor Documentation <http://django-compressor.readthedocs.org/en/latest/>`_
|
||||
|
||||
|
||||
Vagrant configuration
|
||||
---------------------
|
||||
|
||||
Location: ``/Vagrantfile`` and ``/vagrant/``
|
||||
|
||||
If you have Vagrant installed, these files let you easily setup a development environment with PostgreSQL and Elasticsearch inside a virtual machine.
|
||||
|
||||
See below section `With Vagrant`_ for info on how to use Vagrant in development
|
||||
|
||||
If you do not want to use Vagrant, you can just delete these files.
|
||||
|
||||
|
||||
Django settings
|
||||
---------------
|
||||
|
||||
Location: ``/mysite/mysite/settings/``
|
||||
|
||||
The Django settings files are split up into ``base.py``, ``dev.py``, ``production.py`` and ``local.py``.
|
||||
|
||||
.. glossary::
|
||||
|
||||
``base.py``
|
||||
|
||||
This file is for global settings that will be used in both development and production. Aim to keep most of your configuration in this file.
|
||||
|
||||
``dev.py``
|
||||
|
||||
This file is for settings that will only be used by developers. For example: ``DEBUG = True``
|
||||
|
||||
``production.py``
|
||||
|
||||
This file is for settings that will only run on a production server. For example: ``DEBUG = False``
|
||||
|
||||
``local.py``
|
||||
|
||||
This file is used for settings local to a particular machine. This file should never be tracked by a version control system.
|
||||
|
||||
.. tip::
|
||||
|
||||
On production servers, we recommend that you only store secrets in local.py (such as API keys and passwords). This can save you headaches in the future if you are ever trying to debug why a server is behaving badly. If you are using multiple servers which need different settings then we recommend that you create a different ``production.py`` file for each one.
|
||||
|
||||
|
||||
Getting it running
|
||||
==================
|
||||
|
||||
|
||||
With Vagrant
|
||||
------------
|
||||
|
||||
This is the easiest way to get the project running. Vagrant runs your project locally in a virtual machine so you can use PostgreSQL and Elasticsearch in development without having to install them on your host machine. If you haven't yet installed Vagrant, see: `Installing Vagrant <https://docs.vagrantup.com/v2/installation/>`_.
|
||||
|
||||
|
||||
To setup the Vagrant box, run the following commands
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vagrant up # This may take some time on first run
|
||||
vagrant ssh
|
||||
# within the ssh session
|
||||
dj createsuperuser
|
||||
djrun
|
||||
|
||||
|
||||
If you now visit http://localhost:8111 you should see a very basic "Welcome to your new Wagtail site!" page.
|
||||
|
||||
You can browse the Wagtail admin interface at: http://localhost:8111/admin
|
||||
|
||||
You can read more about how Vagrant works at: https://docs.vagrantup.com/v2/
|
||||
|
||||
|
||||
.. topic:: The ``dj`` and ``djrun`` aliases
|
||||
|
||||
When using Vagrant, the Wagtail template provides two aliases: ``dj`` and ``djrun`` which can be used in the ``vagrant ssh`` session.
|
||||
|
||||
.. glossary::
|
||||
|
||||
``dj``
|
||||
|
||||
This is short for ``python manage.py`` so you can use it to reduce typing. For example: ``python manage.py syncdb`` becomes ``dj syncdb``.
|
||||
|
||||
``djrun``
|
||||
|
||||
This is short for ``python manage.py runserver 0.0.0.0:8000``. This is used to run the testing server which is accessible from ``http://localhost:8111`` (note that the port number gets changed by Vagrant)
|
|
@ -0,0 +1,9 @@
|
|||
Getting started
|
||||
===============
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation
|
||||
creating_your_project
|
|
@ -0,0 +1,166 @@
|
|||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
Before you start
|
||||
================
|
||||
|
||||
A basic Wagtail setup can be installed on your machine with only a few prerequisites - see `A basic Wagtail installation`_. However, there are various optional components that will improve the performance and feature set of Wagtail, and our recommended software stack includes the PostgreSQL database, ElasticSearch (for free-text searching), the OpenCV library (for image feature detection), and Redis (as a cache and message queue backend). This would be a lot to install in one go, and for this reason, we provide a virtual machine image, for use with `Vagrant <http://www.vagrantup.com/>`__, with all of these components ready installed.
|
||||
|
||||
Whether you just want to try out the demo site, or you're ready to dive in and create a Wagtail site with all bells and whistles enabled, we strongly recommend the Vagrant approach. Nevertheless, if you're the sort of person who balks at the idea of downloading a whole operating system just to run a web app, we've got you covered too. Start from `A basic Wagtail installation`_ below.
|
||||
|
||||
|
||||
The demo site (a.k.a. the no-installation route)
|
||||
================================================
|
||||
|
||||
We provide a demo site containing a set of standard templates and page types - if you're new to Wagtail, this is the best way to try it out and familiarise yourself with how Wagtail works from the point of view of an editor.
|
||||
|
||||
If you're happy to use Vagrant, and you just want to set up the Wagtail demo site, or any other pre-existing Wagtail site that ships with Vagrant support, you don't need to install Wagtail at all. Install `Vagrant <http://www.vagrantup.com/>`__ and `VirtualBox <https://www.virtualbox.org/>`__, and run::
|
||||
|
||||
git clone https://github.com/torchbox/wagtaildemo.git
|
||||
cd wagtaildemo
|
||||
vagrant up
|
||||
vagrant ssh
|
||||
|
||||
|
||||
Then, within the SSH session::
|
||||
|
||||
./manage.py createsuperuser
|
||||
./manage.py runserver 0.0.0.0:8000
|
||||
|
||||
|
||||
This will make the demo site available on your host machine at the URL http://localhost:8111/ - you can access the Wagtail admin interface at http://localhost:8111/admin/ . Further instructions can be found at :ref:`editor_manual`.
|
||||
|
||||
Once you’ve experimented with the demo site and are ready to build your own site, it's time to install Wagtail on your host machine. Even if you intend to do all further Wagtail work within Vagrant, installing the Wagtail package on your host machine will provide the ``wagtail start`` command that sets up the initial file structure for your project.
|
||||
|
||||
|
||||
A basic Wagtail installation
|
||||
============================
|
||||
|
||||
This provides everything you need to create a new Wagtail project from scratch, containing no page definitions or templates other than a basic homepage as a starting point for building your site. (For a gentler introduction to Wagtail, you may wish to try out the demo site first!)
|
||||
|
||||
You will need Python's `pip <http://pip.readthedocs.org/en/latest/installing.html>`__ package manager. We also recommend `virtualenvwrapper <http://virtualenvwrapper.readthedocs.org/en/latest/>`_ so that you can manage multiple independent Python environments for different projects - although this is not strictly necessary if you intend to do all your development under Vagrant.
|
||||
|
||||
Wagtail is based on the Django web framework and various other Python libraries. Most of these are pure Python and will install automatically using ``pip``, but there are a few native-code components that require further attention:
|
||||
|
||||
* libsass-python (for compiling SASS stylesheets) - requires a C++ compiler and the Python development headers.
|
||||
* Pillow (for image processing) - additionally requires libjpeg and zlib.
|
||||
|
||||
On Debian or Ubuntu, these can be installed with the command::
|
||||
|
||||
sudo apt-get install python-dev python-pip g++ libjpeg62-dev zlib1g-dev
|
||||
|
||||
With these dependencies installed, Wagtail can then be installed with the command::
|
||||
|
||||
pip install wagtail
|
||||
|
||||
(or if you're not using virtualenvwrapper: ``sudo pip install wagtail``.)
|
||||
|
||||
You will now be able to run the following command to set up an initial file structure for your Wagtail project (replace ``myprojectname`` with a name of your choice)::
|
||||
|
||||
wagtail start myprojectname
|
||||
|
||||
**Without Vagrant:** Run the following steps to complete setup of your project (the ``migrate`` step will prompt you to set up a superuser account)::
|
||||
|
||||
cd myprojectname
|
||||
pip install -r requirements.txt
|
||||
python manage.py syncdb
|
||||
python manage.py migrate
|
||||
python manage.py runserver
|
||||
|
||||
Your site is now accessible at http://localhost:8000, with the admin backend available at http://localhost:8000/admin/ .
|
||||
|
||||
**With Vagrant:** Run the following steps to bring up the virtual machine and complete setup of your project (the ``createsuperuser`` step will prompt you to set up a superuser account)::
|
||||
|
||||
cd myprojectname
|
||||
vagrant up
|
||||
vagrant ssh
|
||||
./manage.py createsuperuser
|
||||
./manage.py runserver 0.0.0.0:8000
|
||||
|
||||
Your site is now accessible at http://localhost:8111, with the admin backend available at http://localhost:8111/admin/ .
|
||||
|
||||
Optional extras
|
||||
===============
|
||||
|
||||
For the best possible performance and feature set, we recommend setting up the following components. If you're using Vagrant, these are provided as part of the virtual machine image and just need to be enabled in the settings for your project. If you're using Wagtail without Vagrant, this will involve additional installation.
|
||||
|
||||
|
||||
PostgreSQL
|
||||
----------
|
||||
PostgreSQL is a mature database engine suitable for production use, and is recommended by the Django development team. Non-Vagrant users will need to install the PostgreSQL development headers in addition to Postgres itself; on Debian or Ubuntu, this can be done with the following command::
|
||||
|
||||
sudo apt-get install postgresql postgresql-server-dev-all
|
||||
|
||||
To enable Postgres for your project, uncomment the ``psycopg2`` line from your project's requirements.txt, and in ``myprojectname/settings/base.py``, uncomment the DATABASES section for PostgreSQL, commenting out the SQLite one instead. Then run::
|
||||
|
||||
pip install -r requirements.txt
|
||||
createdb -Upostgres myprojectname
|
||||
./manage.py syncdb
|
||||
./manage.py migrate
|
||||
|
||||
This assumes that your PostgreSQL instance is configured to allow you to connect as the 'postgres' user - if not, you'll need to adjust the ``createdb`` line and the database settings in settings/base.py accordingly.
|
||||
|
||||
|
||||
ElasticSearch
|
||||
-------------
|
||||
Wagtail integrates with ElasticSearch to provide full-text searching of your content, both within the Wagtail interface and on your site's front-end. If ElasticSearch is not available, Wagtail will fall back to much more basic search functionality using database queries. ElasticSearch is pre-installed as part of the Vagrant virtual machine image; non-Vagrant users can use the `debian.sh <https://github.com/torchbox/wagtail/blob/master/scripts/install/debian.sh>`__ or `ubuntu.sh <https://github.com/torchbox/wagtail/blob/master/scripts/install/ubuntu.sh>`__ installation scripts as a guide.
|
||||
|
||||
To enable ElasticSearch for your project, uncomment the ``elasticsearch`` line from your project's requirements.txt, and in ``myprojectname/settings/base.py``, uncomment the WAGTAILSEARCH_BACKENDS section. Then run::
|
||||
|
||||
pip install -r requirements.txt
|
||||
./manage.py update_index
|
||||
|
||||
|
||||
Image feature detection
|
||||
-----------------------
|
||||
Wagtail can use the OpenCV computer vision library to detect faces and other features in images, and use this information to select the most appropriate centre point when cropping the image. OpenCV is pre-installed as part of the Vagrant virtual machine image, and Vagrant users can enable this by setting ``WAGTAILIMAGES_FEATURE_DETECTION_ENABLED`` to True in ``myprojectname/settings/base.py``. For installation outside of Vagrant, see :ref:`image_feature_detection`.
|
||||
|
||||
|
||||
Alternative installation methods
|
||||
================================
|
||||
|
||||
Ubuntu
|
||||
------
|
||||
|
||||
If you have a fresh instance of Ubuntu 13.04 or later, you can install Wagtail,
|
||||
along with a demonstration site containing a set of standard templates and page
|
||||
types, in one step. As the root user::
|
||||
|
||||
curl -O https://wagtail.io/ubuntu.sh; bash ubuntu.sh
|
||||
|
||||
This script installs all the dependencies for a production-ready Wagtail site,
|
||||
including PostgreSQL, Redis, Elasticsearch, Nginx and uwsgi. We
|
||||
recommend you check through the script before running it, and adapt it according
|
||||
to your deployment preferences. The canonical version is at
|
||||
`github.com/torchbox/wagtail/blob/master/scripts/install/ubuntu.sh
|
||||
<https://github.com/torchbox/wagtail/blob/master/scripts/install/ubuntu.sh>`_.
|
||||
|
||||
|
||||
Debian
|
||||
------
|
||||
|
||||
If you have a fresh instance of Debian 7, you can install Wagtail, along with a
|
||||
demonstration site containing a set of standard templates and page types, in one
|
||||
step. As the root user::
|
||||
|
||||
curl -O https://wagtail.io/debian.sh; bash debian.sh
|
||||
|
||||
This script installs all the dependencies for a production-ready Wagtail site,
|
||||
including PostgreSQL, Redis, Elasticsearch, Nginx and uwsgi. We
|
||||
recommend you check through the script before running it, and adapt it according
|
||||
to your deployment preferences. The canonical version is at
|
||||
`github.com/torchbox/wagtail/blob/master/scripts/install/debian.sh
|
||||
<https://github.com/torchbox/wagtail/blob/master/scripts/install/debian.sh>`_.
|
||||
|
||||
Docker
|
||||
------
|
||||
|
||||
`@oyvindsk <https://github.com/oyvindsk>`_ has built a Dockerfile for the Wagtail demo. Simply run::
|
||||
|
||||
docker run -p 8000:8000 -d oyvindsk/wagtail-demo
|
||||
|
||||
then access the site at http://your-ip:8000 and the admin
|
||||
interface at http://your-ip:8000/admin using admin / test.
|
||||
|
||||
See https://index.docker.io/u/oyvindsk/wagtail-demo/ for more details.
|
|
@ -1,169 +0,0 @@
|
|||
Getting Started
|
||||
---------------
|
||||
|
||||
On Ubuntu
|
||||
~~~~~~~~~
|
||||
|
||||
If you have a fresh instance of Ubuntu 13.04 or later, you can install Wagtail,
|
||||
along with a demonstration site containing a set of standard templates and page
|
||||
types, in one step. As the root user::
|
||||
|
||||
curl -O https://wagtail.io/ubuntu.sh; bash ubuntu.sh
|
||||
|
||||
This script installs all the dependencies for a production-ready Wagtail site,
|
||||
including PostgreSQL, Redis, Elasticsearch, Nginx and uwsgi. We
|
||||
recommend you check through the script before running it, and adapt it according
|
||||
to your deployment preferences. The canonical version is at
|
||||
`github.com/torchbox/wagtail/blob/master/scripts/install/ubuntu.sh
|
||||
<https://github.com/torchbox/wagtail/blob/master/scripts/install/ubuntu.sh>`_.
|
||||
|
||||
Once you've experimented with the demo app and are ready to build your pages via your own app you can `remove the demo app`_ if you choose.
|
||||
|
||||
On Debian
|
||||
~~~~~~~~~
|
||||
|
||||
If you have a fresh instance of Debian 7, you can install Wagtail, along with a
|
||||
demonstration site containing a set of standard templates and page types, in one
|
||||
step. As the root user::
|
||||
|
||||
curl -O https://wagtail.io/debian.sh; bash debian.sh
|
||||
|
||||
This script installs all the dependencies for a production-ready Wagtail site,
|
||||
including PostgreSQL, Redis, Elasticsearch, Nginx and uwsgi. We
|
||||
recommend you check through the script before running it, and adapt it according
|
||||
to your deployment preferences. The canonical version is at
|
||||
`github.com/torchbox/wagtail/blob/master/scripts/install/debian.sh
|
||||
<https://github.com/torchbox/wagtail/blob/master/scripts/install/debian.sh>`_.
|
||||
|
||||
Once you've experimented with the demo app and are ready to build your pages via your own app you can `remove the demo app`_ if you choose.
|
||||
|
||||
On OS X
|
||||
~~~~~~~
|
||||
|
||||
Install `pip <http://pip.readthedocs.org/en/latest/installing.html>`__ and `virtualenvwrapper <http://virtualenvwrapper.readthedocs.org/en/latest/>`_ if you don't have them already. Then, in your terminal::
|
||||
|
||||
mkvirtualenv wagtaildemo
|
||||
git clone https://github.com/torchbox/wagtaildemo.git
|
||||
cd wagtaildemo
|
||||
pip install -r requirements/dev.txt
|
||||
|
||||
Edit ``wagtaildemo/settings/base.py``, changing ENGINE to django.db.backends.sqlite3 and NAME to wagtail.db. Finally, setup the database and run the local server::
|
||||
|
||||
./manage.py syncdb
|
||||
./manage.py migrate
|
||||
./manage.py runserver
|
||||
|
||||
Using Vagrant
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
We provide a Vagrant box which includes all the dependencies for a fully-fledged
|
||||
Wagtail environment, bundled with a demonstration site containing a set of
|
||||
standard templates and page types. If you have a good internet connection we recommend
|
||||
the following steps, which will download the 650MB Vagrant box and make a running
|
||||
Wagtail instance available as the basis for your new site:
|
||||
|
||||
- Install `Vagrant <http://www.vagrantup.com/>`_ 1.1+
|
||||
- Clone the demonstration site, create the Vagrant box and initialise Wagtail::
|
||||
|
||||
git clone https://github.com/torchbox/wagtaildemo.git
|
||||
cd wagtaildemo
|
||||
vagrant up
|
||||
vagrant ssh
|
||||
# within the SSH session
|
||||
./manage.py createsuperuser
|
||||
./manage.py update_index
|
||||
./manage.py runserver 0.0.0.0:8000
|
||||
|
||||
- This will make the app accessible on the host machine as
|
||||
`localhost:8111 <http://localhost:8111>`_ - you can access the Wagtail admin
|
||||
interface at `localhost:8111/admin <http://localhost:8111/admin>`_. The codebase
|
||||
is located on the host machine, exported to the VM as a shared folder; code
|
||||
editing and Git operations will generally be done on the host.
|
||||
|
||||
Using Docker
|
||||
~~~~~~~~~~~~
|
||||
|
||||
`@oyvindsk <https://github.com/oyvindsk>`_ has built a Dockerfile for the Wagtail demo. Simply run::
|
||||
|
||||
docker run -p 8000:8000 -d oyvindsk/wagtail-demo
|
||||
|
||||
then access the site at http://your-ip:8000 and the admin
|
||||
interface at http://your-ip:8000/admin using admin / test.
|
||||
|
||||
See https://index.docker.io/u/oyvindsk/wagtail-demo/ for more details.
|
||||
|
||||
Other platforms
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
If you're not using Ubuntu or Debian, or if you prefer to install Wagtail manually,
|
||||
use the following steps:
|
||||
|
||||
Required dependencies
|
||||
=====================
|
||||
|
||||
- `pip <https://github.com/pypa/pip>`__
|
||||
- `libjpeg <http://ijg.org/>`_
|
||||
- `libxml2 <http://xmlsoft.org/>`_
|
||||
- `libxslt <http://xmlsoft.org/XSLT/>`_
|
||||
- `zlib <http://www.zlib.net/>`_
|
||||
|
||||
Optional dependencies
|
||||
=====================
|
||||
|
||||
- `PostgreSQL`_
|
||||
- `Elasticsearch`_
|
||||
- `Redis`_
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
With PostgreSQL running (and configured to allow you to connect as the
|
||||
'postgres' user - if not, you'll need to adjust the ``createdb`` line
|
||||
and the database settings in wagtaildemo/settings/base.py accordingly),
|
||||
run the following commands::
|
||||
|
||||
git clone https://github.com/torchbox/wagtaildemo.git
|
||||
cd wagtaildemo
|
||||
pip install -r requirements/dev.txt
|
||||
createdb -Upostgres wagtaildemo
|
||||
./manage.py syncdb
|
||||
./manage.py migrate
|
||||
./manage.py runserver
|
||||
|
||||
SQLite support
|
||||
==============
|
||||
|
||||
SQLite is supported as an alternative to PostgreSQL - update the DATABASES setting
|
||||
in wagtaildemo/settings/base.py to use 'django.db.backends.sqlite3', as you would
|
||||
with a regular Django project.
|
||||
|
||||
.. _Wagtail: http://wagtail.io
|
||||
.. _VirtualBox: https://www.virtualbox.org/
|
||||
.. _the Wagtail codebase: https://github.com/torchbox/wagtail
|
||||
.. _PostgreSQL: http://www.postgresql.org
|
||||
.. _Elasticsearch: http://www.elasticsearch.org
|
||||
.. _Redis: http://redis.io/
|
||||
|
||||
_`Remove the demo app`
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you've experimented with the demo app and are ready to build your pages via your own app you can remove the demo app if you choose.
|
||||
|
||||
``PROJECT_ROOT`` should be where your project is located (e.g. /usr/local/django) and ``PROJECT`` is the name of your project (e.g. mywagtail)::
|
||||
|
||||
export PROJECT_ROOT=/usr/local/django
|
||||
export PROJECT=mywagtail
|
||||
cd $PROJECT_ROOT/$PROJECT
|
||||
./manage.py sqlclear demo | psql -Upostgres $PROJECT -f -
|
||||
psql -Upostgres $PROJECT << EOF
|
||||
BEGIN;
|
||||
DELETE FROM wagtailcore_site WHERE root_page_id IN (SELECT id FROM wagtailcore_page WHERE content_type_id IN (SELECT id FROM django_content_type where app_label='demo'));
|
||||
DELETE FROM wagtailcore_page WHERE content_type_id IN (SELECT id FROM django_content_type where app_label='demo');
|
||||
DELETE FROM auth_permission WHERE content_type_id IN (SELECT id FROM django_content_type where app_label='demo');
|
||||
DELETE FROM django_content_type WHERE app_label='demo';
|
||||
DELETE FROM wagtailimages_rendition;
|
||||
DELETE FROM wagtailimages_image;
|
||||
COMMIT;
|
||||
EOF
|
||||
rm -r demo media/images/* media/original_images/*
|
||||
perl -pi -e"s/('demo',|WAGTAILSEARCH_RESULTS_TEMPLATE)/#\1/" $PROJECT/settings/base.py
|
|
@ -8,4 +8,5 @@ How to
|
|||
settings
|
||||
deploying
|
||||
performance
|
||||
multilingual_sites
|
||||
contributing
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
===========================
|
||||
Creating multilingual sites
|
||||
===========================
|
||||
|
||||
This tutorial will show you a method of creating multilingual sites in Wagtail.
|
||||
|
||||
Currently, Wagtail doesn't support multiple languages in the same page. The recommended way of creating multilingual websites in Wagtail at the moment is to create one section of your website for each language.
|
||||
|
||||
For example::
|
||||
|
||||
/
|
||||
en/
|
||||
about/
|
||||
contact/
|
||||
fr/
|
||||
about/
|
||||
contact/
|
||||
|
||||
|
||||
The root page
|
||||
=============
|
||||
|
||||
The root page (``/``) should detect the browsers language and forward them to the correct language homepage (``/en/``, ``/fr/``). This page should sit at the site root (where the homepage would normally be).
|
||||
|
||||
We must set Djangos ``LANGUAGES`` setting so we don't redirect non English/French users to pages that don't exist.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# settings.py
|
||||
LANGUAGES = (
|
||||
('en', _("English")),
|
||||
('fr', _("French")),
|
||||
)
|
||||
|
||||
# models.py
|
||||
from django.utils import translation
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
class LanguageRedirectionPage(Page):
|
||||
|
||||
def serve(self, request):
|
||||
# This will only return a language that is in the LANGUAGES Django setting
|
||||
language = translation.get_language_from_request(request)
|
||||
|
||||
return HttpResponseRedirect(self.url + language + '/')
|
||||
|
||||
|
||||
Linking pages together
|
||||
======================
|
||||
|
||||
It may be useful to link different versions of the same page together to allow the user to easily switch between languages. But we don't want to increse the burdon on the editor too much so ideally, editors should only need to link one of the pages to the other versions and the links between the other versions should be created implicitly.
|
||||
|
||||
As this behaviour needs to be added to all page types that would be translated, its best to put this behaviour in a mixin.
|
||||
|
||||
Heres an example of how this could be implemented (with English as the main language and French/Spanish as alternative languages):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class TranslatablePageMixin(models.Model):
|
||||
# One link for each alternative language
|
||||
# These should only be used on the main language page (english)
|
||||
french_link = models.ForeignKey(Page, null=True, on_delete=models.SET_NULL, blank=True, related_name='+')
|
||||
spanish_link = models.ForeignKey(Page, null=True, on_delete=models.SET_NULL, blank=True, related_name='+')
|
||||
|
||||
def get_language(self):
|
||||
"""
|
||||
This returns the language code for this page.
|
||||
"""
|
||||
# Look through ancestors of this page for its language homepage
|
||||
# The language homepage is located at depth 3
|
||||
language_homepage = self.get_ancestors(inclusive=True).get(depth=3)
|
||||
|
||||
# The slug of language homepages should always be set to the language code
|
||||
return language_homepage.slug
|
||||
|
||||
|
||||
# Method to find the main language version of this page
|
||||
# This works by reversing the above links
|
||||
|
||||
def english_page(self):
|
||||
"""
|
||||
This finds the english version of this page
|
||||
"""
|
||||
language = self.get_language()
|
||||
|
||||
if language == 'en':
|
||||
return self
|
||||
elif language == 'fr':
|
||||
return type(self).objects.filter(french_link=self).first().specific
|
||||
elif language == 'es':
|
||||
return type(self).objects.filter(spanish_link=self).first().specific
|
||||
|
||||
|
||||
# We need a method to find a version of this page for each alternative language.
|
||||
# These all work the same way. They firstly find the main version of the page
|
||||
# (english), then from there they can just follow the link to the correct page.
|
||||
|
||||
def french_page(self):
|
||||
"""
|
||||
This finds the french version of this page
|
||||
"""
|
||||
english_page = self.english_page()
|
||||
|
||||
if english_page and english_page.french_link:
|
||||
return english_page.french_link.specific
|
||||
|
||||
def spanish_page(self):
|
||||
"""
|
||||
This finds the spanish version of this page
|
||||
"""
|
||||
english_page = self.english_page()
|
||||
|
||||
if english_page and english_page.spanish_link:
|
||||
return english_page.spanish_link.specific
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class AboutPage(Page, TranslatablePageMixin):
|
||||
...
|
||||
|
||||
|
||||
class ContactPage(Page, TranslatablePageMixin):
|
||||
...
|
||||
|
||||
|
||||
You can make use of these methods in your template by doing:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% if self.english_page and self.get_language != 'en' %}
|
||||
<a href="{{ self.english_page.url }}">{% trans "View in English" %}</a>
|
||||
{% endif %}
|
||||
|
||||
{% if self.french_page and self.get_language != 'fr' %}
|
||||
<a href="{{ self.french_page.url }}">{% trans "View in French" %}</a>
|
||||
{% endif %}
|
||||
|
||||
{% if self.spanish_page and self.get_language != 'es' %}
|
||||
<a href="{{ self.spanish_page.url }}">{% trans "View in Spanish" %}</a>
|
||||
{% endif %}
|
|
@ -13,7 +13,7 @@ We have tried to minimise external dependencies for a working installation of Wa
|
|||
Cache
|
||||
-----
|
||||
|
||||
We recommend `Redis <http://redis.io/>`_ as a fast, persistent cache. Install Redis through package manager and enable it as a cache backend::
|
||||
We recommend `Redis <http://redis.io/>`_ as a fast, persistent cache. Install Redis through your package manager (on Debian or Ubuntu: ``sudo apt-get install redis-server``), add ``django-redis-cache`` to your requirements.txt, and enable it as a cache backend::
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
|
@ -25,7 +25,22 @@ We recommend `Redis <http://redis.io/>`_ as a fast, persistent cache. Install Re
|
|||
}
|
||||
}
|
||||
|
||||
Without a persistent cache, Wagtail will recreate all compressable assets at each server start, e.g. when any files change under ```./manage.py runserver```.
|
||||
Without a persistent cache, Wagtail will recreate all compressable assets at each server start, e.g. when any files change under ``./manage.py runserver``.
|
||||
|
||||
|
||||
Sending emails in the background using Celery
|
||||
---------------------------------------------
|
||||
|
||||
Various actions in the Wagtail admin backend can trigger notification emails - for example, submitting a page for moderation. In Wagtail's default configuration, these are sent as part of the page request/response cycle, which means that web server threads can get tied up for long periods if many emails are being sent. To avoid this, Wagtail can be configured to do this as a background task, using `Celery <http://www.celeryproject.org/>`_ as a task queue. To install Celery, add ``django-celery`` to your requirements.txt. A sample configuration, using Redis as the queue backend, would look like::
|
||||
|
||||
import djcelery
|
||||
|
||||
djcelery.setup_loader()
|
||||
|
||||
CELERY_SEND_TASK_ERROR_EMAILS = True
|
||||
BROKER_URL = 'redis://'
|
||||
|
||||
See the Celery documentation for instructions on running the worker process in development or production.
|
||||
|
||||
|
||||
Search
|
||||
|
|
|
@ -3,12 +3,12 @@ Welcome to Wagtail's documentation
|
|||
|
||||
Wagtail is a modern, flexible CMS, built on Django.
|
||||
|
||||
It supports Django 1.6.2+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4. Django 1.7 support is in progress pending further release candidate testing.
|
||||
It supports Django 1.6.2+ and 1.7rc3+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
gettingstarted
|
||||
getting_started/index
|
||||
core_components/index
|
||||
contrib_components/index
|
||||
howto/index
|
||||
|
|
|
@ -158,6 +158,8 @@ The scheduled publishing mechanism adds an ``expired`` field to wagtailcore.Page
|
|||
'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
|
||||
|
||||
.. _04_deprecated_features:
|
||||
|
||||
Deprecated features
|
||||
===================
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ RoutablePage
|
|||
|
||||
A ``RoutablePage`` model has been added to allow embedding Django-style URL routing within a page.
|
||||
|
||||
:ref:`routable_page`
|
||||
:ref:`routable_page_mixin`
|
||||
|
||||
|
||||
Usage stats for images, documents and snippets
|
||||
|
@ -122,3 +122,11 @@ Several new fields have been added to the Image and Rendition models to support
|
|||
./manage.py schemamigration myapp --auto add_image_focal_point_fields
|
||||
|
||||
(with 'myapp' replaced with your app name) will generate the necessary migration file.
|
||||
|
||||
|
||||
South upgraded to 1.0
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In preparation for Django 1.7 support in a future release, Wagtail now depends on South 1.0, and its migration files have been moved from ``migrations`` to ``south_migrations``. Older versions of South will fail to find the migrations in the new location.
|
||||
|
||||
If your project's requirements file (most commonly requirements.txt or requirements/base.txt) references a specific older version of South, this must be updated to South 1.0.
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
=========================
|
||||
Wagtail 0.6 release notes
|
||||
=========================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
|
||||
What's new
|
||||
==========
|
||||
|
||||
Project template and start project command
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Wagtail now has a basic project template built in to make starting new projects much easier.
|
||||
|
||||
To use it, install ``wagtail`` onto your machine and run ``wagtail start project_name``.
|
||||
|
||||
Django 1.7 support
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Wagtail can now be used with Django 1.7.
|
||||
|
||||
|
||||
Minor features
|
||||
~~~~~~~~~~~~~~
|
||||
* A new template tag has been added for reversing URLs inside routable pages. See :ref:`routablepageurl_template_tag`.
|
||||
* RoutablePage can now be used as a mixin. See :class:`wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin`.
|
||||
* MenuItems can now have bundled JavaScript
|
||||
* Added the ``register_admin_menu_item`` hook for registering menu items at startup. See :ref:`admin_hooks`
|
||||
* Added a version indicator into the admin interface (hover over the wagtail to see it)
|
||||
* Added Russian translation
|
||||
|
||||
|
||||
Bug fixes
|
||||
~~~~~~~~~
|
||||
|
||||
* Page URL generation now returns correct URLs for sites that have the main 'serve' view rooted somewhere other than '/'.
|
||||
* Search results in the page chooser now respect the page_type parameter on PageChooserPanel.
|
||||
* Rendition filenames are now prevented from going over 60 chars, even with a large focal_point_key.
|
||||
* Child relations that are defined on a model's superclass (such as the base Page model) are now picked up correctly by the page editing form, page copy operations and the replace_text management command.
|
||||
* Tags on images and documents are now committed to the search index immediately on saving.
|
||||
|
||||
|
||||
Upgrade considerations
|
||||
======================
|
||||
|
||||
All features deprecated in 0.4 have been removed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See: :ref:`04_deprecated_features`
|
||||
|
||||
|
||||
Deprecated features
|
||||
===================
|
||||
|
||||
* The ``wagtail.wagtailsearch.indexed`` module has been renamed to ``wagtail.wagtailsearch.index``
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
==========================================
|
||||
Wagtail 0.7 release notes - IN DEVELOPMENT
|
||||
==========================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
|
||||
What's new
|
||||
==========
|
||||
|
||||
New interface for choosing images focal point
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
Minor features
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
* The ``content_type`` template filter has been removed from the project template, as the same thing can be accomplished with ``self.get_verbose_name|slugify``.
|
||||
* Page copy operations now also copy the page revision history.
|
||||
* Page models now support a ``parent_page_types`` property in addition to ``subpage types``, to restrict the types of page they can be created under.
|
||||
* ``register_snippet`` can now be invoked as a decorator.
|
||||
|
||||
Bug fixes
|
||||
~~~~~~~~~
|
||||
|
||||
|
||||
Upgrade considerations
|
||||
======================
|
||||
|
||||
|
||||
Deprecated features
|
||||
===================
|
|
@ -5,6 +5,8 @@ Release notes
|
|||
:maxdepth: 1
|
||||
|
||||
roadmap
|
||||
0.7
|
||||
0.6
|
||||
0.5
|
||||
0.4.1
|
||||
0.4
|
||||
|
|
|
@ -3,3 +3,4 @@ coverage==3.7.1
|
|||
flake8==2.2.1
|
||||
mock==1.0.1
|
||||
python-dateutil==2.2
|
||||
pytz==2014.7
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import warnings
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
|
@ -12,6 +13,9 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'wagtail.tests.settings'
|
|||
|
||||
|
||||
def runtests():
|
||||
# Don't ignore DeprecationWarnings
|
||||
warnings.simplefilter('default', DeprecationWarning)
|
||||
|
||||
argv = sys.argv[:1] + ['test'] + sys.argv[1:]
|
||||
try:
|
||||
execute_from_command_line(argv)
|
||||
|
|
|
@ -36,7 +36,7 @@ aptitude update
|
|||
aptitude -y install git python-pip nginx postgresql redis-server
|
||||
aptitude -y install postgresql-server-dev-all python-dev libjpeg62-dev
|
||||
|
||||
perl -pi -e "s/^(local\s+all\s+postgres\s+)peer$/\1trust/" /etc/postgresql/9.1/main/pg_hba.conf
|
||||
perl -pi -e "s/^(local\s+all\s+postgres\s+)peer$/\1trust/" /etc/postgresql/9.3/main/pg_hba.conf
|
||||
service postgresql reload
|
||||
|
||||
aptitude -y install openjdk-7-jre-headless
|
||||
|
|
27
setup.py
27
setup.py
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import sys, os
|
||||
|
||||
from wagtail.wagtailcore import __version__
|
||||
|
||||
|
||||
try:
|
||||
|
@ -9,26 +11,29 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
|
||||
# Hack to prevent stupid TypeError: 'NoneType' object is not callable error on
|
||||
# exit of python setup.py test # in multiprocessing/util.py _exit_function when
|
||||
# running python setup.py test (see
|
||||
# http://www.eby-sarna.com/pipermail/peak/2010-May/003357.html)
|
||||
# Hack to prevent "TypeError: 'NoneType' object is not callable" error
|
||||
# in multiprocessing/util.py _exit_function when setup.py exits
|
||||
# (see http://www.eby-sarna.com/pipermail/peak/2010-May/003357.html)
|
||||
try:
|
||||
import multiprocessing
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
# Disable parallel builds, because Pillow 2.5.3 does some crazy monkeypatching of
|
||||
# the build process on multicore systems, which breaks installation of libsass
|
||||
os.environ['MAX_CONCURRENCY'] = '1'
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
|
||||
install_requires = [
|
||||
"Django>=1.6.2,<1.7",
|
||||
"Django>=1.6.2,<1.8",
|
||||
"South==1.0.0",
|
||||
"django-compressor>=1.4",
|
||||
"django-libsass>=0.2",
|
||||
"django-modelcluster>=0.3",
|
||||
"django-taggit==0.12.0",
|
||||
"django-modelcluster>=0.4",
|
||||
"django-taggit==0.12.1",
|
||||
"django-treebeard==2.0",
|
||||
"Pillow>=2.3.0",
|
||||
"beautifulsoup4>=4.3.2",
|
||||
|
@ -47,7 +52,7 @@ if not PY3:
|
|||
|
||||
setup(
|
||||
name='wagtail',
|
||||
version='0.5',
|
||||
version=__version__,
|
||||
description='A Django content management system focused on flexibility and user experience',
|
||||
author='Matthew Westcott',
|
||||
author_email='matthew.westcott@torchbox.com',
|
||||
|
@ -74,5 +79,9 @@ setup(
|
|||
'Topic :: Internet :: WWW/HTTP :: Site Management',
|
||||
],
|
||||
install_requires=install_requires,
|
||||
entry_points="""
|
||||
[console_scripts]
|
||||
wagtail=wagtail.bin.wagtail:main
|
||||
""",
|
||||
zip_safe=False,
|
||||
)
|
||||
|
|
158
tox.ini
158
tox.ini
|
@ -1,11 +1,41 @@
|
|||
[deps]
|
||||
dj16=
|
||||
Django>=1.6,<1.7
|
||||
base =
|
||||
South==1.0.0
|
||||
django-compressor>=1.4
|
||||
django-libsass>=0.2
|
||||
django-modelcluster>=0.3
|
||||
django-taggit==0.12.1
|
||||
django-treebeard==2.0
|
||||
Pillow>=2.3.0
|
||||
beautifulsoup4>=4.3.2
|
||||
html5lib==0.999
|
||||
Unidecode>=0.04.14
|
||||
six==1.7.3
|
||||
requests==2.3.0
|
||||
elasticsearch==1.1.0
|
||||
mock==1.0.1
|
||||
python-dateutil==2.2
|
||||
pytz==2014.7
|
||||
Embedly
|
||||
coverage
|
||||
|
||||
dj16 =
|
||||
Django>=1.6,<1.7
|
||||
|
||||
|
||||
dj17 =
|
||||
https://github.com/django/django/archive/stable/1.7.x.zip#egg=django
|
||||
|
||||
py2 =
|
||||
unicodecsv>=0.9.4
|
||||
|
||||
py3 =
|
||||
|
||||
|
||||
[tox]
|
||||
skipsdist = True
|
||||
usedevelop = True
|
||||
|
||||
envlist =
|
||||
py26-dj16-postgres,
|
||||
py26-dj16-sqlite,
|
||||
|
@ -13,7 +43,16 @@ envlist =
|
|||
py27-dj16-sqlite,
|
||||
py32-dj16-postgres,
|
||||
py33-dj16-postgres,
|
||||
py34-dj16-postgres
|
||||
py34-dj16-postgres,
|
||||
|
||||
py27-dj17-postgres,
|
||||
py27-dj17-sqlite,
|
||||
py32-dj17-postgres,
|
||||
py32-dj17-sqlite,
|
||||
py33-dj17-postgres,
|
||||
py33-dj17-sqlite,
|
||||
py34-dj17-postgres,
|
||||
py34-dj17-sqlite
|
||||
|
||||
# mysql not currently supported
|
||||
# (wagtail.wagtailimages.tests.TestImageEditView currently fails with a
|
||||
|
@ -28,11 +67,13 @@ envlist =
|
|||
|
||||
|
||||
[testenv]
|
||||
commands=./runtests.py
|
||||
commands=coverage run runtests.py
|
||||
|
||||
[testenv:py26-dj16-postgres]
|
||||
basepython=python2.6
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
|
@ -41,6 +82,8 @@ setenv =
|
|||
[testenv:py26-dj16-sqlite]
|
||||
basepython=python2.6
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
@ -48,6 +91,8 @@ setenv =
|
|||
[testenv:py26-dj16-mysql]
|
||||
basepython=python2.6
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
MySQL-python==1.2.5
|
||||
setenv =
|
||||
|
@ -57,6 +102,8 @@ setenv =
|
|||
[testenv:py27-dj16-postgres]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
|
@ -65,6 +112,8 @@ setenv =
|
|||
[testenv:py27-dj16-sqlite]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
@ -72,6 +121,8 @@ setenv =
|
|||
[testenv:py27-dj16-mysql]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj16}
|
||||
MySQL-python==1.2.5
|
||||
setenv =
|
||||
|
@ -81,6 +132,8 @@ setenv =
|
|||
[testenv:py32-dj16-postgres]
|
||||
basepython=python3.2
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
|
@ -89,6 +142,8 @@ setenv =
|
|||
[testenv:py32-dj16-sqlite]
|
||||
basepython=python3.2
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
@ -96,6 +151,8 @@ setenv =
|
|||
[testenv:py33-dj16-postgres]
|
||||
basepython=python3.3
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
|
@ -104,6 +161,8 @@ setenv =
|
|||
[testenv:py33-dj16-sqlite]
|
||||
basepython=python3.3
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
@ -111,6 +170,8 @@ setenv =
|
|||
[testenv:py34-dj16-postgres]
|
||||
basepython=python3.4
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
|
@ -119,6 +180,95 @@ setenv =
|
|||
[testenv:py34-dj16-sqlite]
|
||||
basepython=python3.4
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj16}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
||||
[testenv:py27-dj17-postgres]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj17}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.postgresql_psycopg2
|
||||
|
||||
[testenv:py27-dj17-sqlite]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj17}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
||||
[testenv:py27-dj17-mysql]
|
||||
basepython=python2.7
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py2}
|
||||
{[deps]dj17}
|
||||
MySQL-python==1.2.5
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.mysql
|
||||
DATABASE_USER=wagtail
|
||||
|
||||
[testenv:py32-dj17-postgres]
|
||||
basepython=python3.2
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.postgresql_psycopg2
|
||||
|
||||
[testenv:py32-dj17-sqlite]
|
||||
basepython=python3.2
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
||||
[testenv:py33-dj17-postgres]
|
||||
basepython=python3.3
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.postgresql_psycopg2
|
||||
|
||||
[testenv:py33-dj17-sqlite]
|
||||
basepython=python3.3
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
||||
[testenv:py34-dj17-postgres]
|
||||
basepython=python3.4
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
psycopg2==2.5.3
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.postgresql_psycopg2
|
||||
|
||||
[testenv:py34-dj17-sqlite]
|
||||
basepython=python3.4
|
||||
deps =
|
||||
{[deps]base}
|
||||
{[deps]py3}
|
||||
{[deps]dj17}
|
||||
setenv =
|
||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python
|
||||
from __future__ import print_function, absolute_import
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import errno
|
||||
import sys
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
|
||||
def create_project(parser, options, args):
|
||||
# Validate args
|
||||
if len(args) < 2:
|
||||
parser.error("Please specify a name for your wagtail installation")
|
||||
elif len(args) > 2:
|
||||
parser.error("Too many arguments")
|
||||
|
||||
project_name = args[1]
|
||||
|
||||
# Make sure given name is not already in use by another python package/module.
|
||||
try:
|
||||
__import__(project_name)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
parser.error("'%s' conflicts with the name of an existing "
|
||||
"Python module and cannot be used as a project "
|
||||
"name. Please try another name." % project_name)
|
||||
|
||||
# Make sure directory does not already exist
|
||||
if os.path.exists(project_name):
|
||||
print('A directory called %(project_name)s already exists. \
|
||||
Please choose another name for your wagtail project or remove the existing directory.' % {'project_name': project_name})
|
||||
sys.exit(errno.EEXIST)
|
||||
|
||||
print("Creating a wagtail project called %(project_name)s" % {'project_name': project_name})
|
||||
|
||||
# Create the project from the wagtail template using startapp
|
||||
|
||||
# First find the path to wagtail
|
||||
import wagtail
|
||||
wagtail_path = os.path.dirname(wagtail.__file__)
|
||||
template_path = os.path.join(wagtail_path, 'project_template')
|
||||
|
||||
# Call django-admin startproject
|
||||
result = subprocess.call([
|
||||
'django-admin.py', 'startproject',
|
||||
'--template=' + template_path,
|
||||
'--name=Vagrantfile', '--ext=html,rst',
|
||||
project_name
|
||||
])
|
||||
|
||||
if result == 0:
|
||||
print("Success! %(project_name)s is created" % {'project_name': project_name})
|
||||
|
||||
|
||||
COMMANDS = {
|
||||
'start': create_project,
|
||||
}
|
||||
|
||||
def main():
|
||||
# Parse options
|
||||
parser = OptionParser(usage="Usage: %prog start project_name")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# Find command
|
||||
try:
|
||||
command = args[0]
|
||||
except IndexError:
|
||||
parser.print_help()
|
||||
return
|
||||
|
||||
if command in COMMANDS:
|
||||
COMMANDS[command](parser, options, args)
|
||||
else:
|
||||
parser.error("Unrecognised command: " + command)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.contrib.wagtailfrontendcache.apps.WagtailFrontendCacheAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailFrontendCacheAppConfig(AppConfig):
|
||||
name = 'wagtail.contrib.wagtailfrontendcache'
|
||||
label = 'wagtailfrontendcache'
|
||||
verbose_name = "Wagtail frontend cache"
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.contrib.wagtailmedusa.apps.WagtailMedusaAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailMedusaAppConfig(AppConfig):
|
||||
name = 'wagtail.contrib.wagtailmedusa'
|
||||
label = 'wagtailmedusa'
|
||||
verbose_name = "Wagtail medusa"
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.contrib.wagtailroutablepage.apps.WagtailRoutablePageAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailRoutablePageAppConfig(AppConfig):
|
||||
name = 'wagtail.contrib.wagtailroutablepage'
|
||||
label = 'wagtailroutablepage'
|
||||
verbose_name = "Wagtail routablepage"
|
|
@ -8,9 +8,10 @@ from wagtail.wagtailcore.models import Page
|
|||
from wagtail.wagtailcore.url_routing import RouteResult
|
||||
|
||||
|
||||
class RoutablePage(Page):
|
||||
class RoutablePageMixin(object):
|
||||
"""
|
||||
This class extends Page by adding methods to allow urlconfs to be embedded inside pages
|
||||
This class can be mixed in to a Page subclass to allow urlconfs to be
|
||||
embedded inside pages.
|
||||
"""
|
||||
#: Set this to a tuple of ``django.conf.urls.url`` objects.
|
||||
subpage_urls = None
|
||||
|
@ -59,7 +60,7 @@ class RoutablePage(Page):
|
|||
except Http404:
|
||||
pass
|
||||
|
||||
return super(RoutablePage, self).route(request, path_components)
|
||||
return super(RoutablePageMixin, self).route(request, path_components)
|
||||
|
||||
def serve(self, request, view, args, kwargs):
|
||||
return view(request, *args, **kwargs)
|
||||
|
@ -68,6 +69,13 @@ class RoutablePage(Page):
|
|||
view, args, kwargs = self.resolve_subpage('/')
|
||||
return view(*args, **kwargs)
|
||||
|
||||
|
||||
class RoutablePage(RoutablePageMixin, Page):
|
||||
"""
|
||||
This class extends Page by adding methods to allow urlconfs
|
||||
to be embedded inside pages
|
||||
"""
|
||||
|
||||
is_abstract = True
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from django import template
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def routablepageurl(context, page, url_name, *args, **kwargs):
|
||||
"""
|
||||
``routablepageurl`` is similar to ``pageurl``, but works with
|
||||
``RoutablePage``\s. It behaves like a hybrid between the built-in
|
||||
``reverse``, and ``pageurl`` from Wagtail.
|
||||
|
||||
``page`` is the RoutablePage that URLs will be generated from.
|
||||
|
||||
``url_name`` is a URL name defined in ``page.subpage_urls``.
|
||||
|
||||
Positional arguments and keyword arguments should be passed as normal
|
||||
positional arguments and keyword arguments.
|
||||
"""
|
||||
request = context['request']
|
||||
base_url = page.relative_url(request.site)
|
||||
routed_url = page.reverse_subpage(url_name, args=args, kwargs=kwargs)
|
||||
return base_url + routed_url
|
|
@ -1,7 +1,8 @@
|
|||
from django.test import TestCase
|
||||
from django.test import TestCase, RequestFactory
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.wagtailcore.models import Page, Site
|
||||
from wagtail.tests.models import RoutablePageTest, routable_page_external_view
|
||||
from wagtail.contrib.wagtailroutablepage.templatetags.wagtailroutablepage_tags import routablepageurl
|
||||
|
||||
|
||||
class TestRoutablePage(TestCase):
|
||||
|
@ -80,3 +81,35 @@ class TestRoutablePage(TestCase):
|
|||
response = self.client.get(self.routable_page.url + 'external/joe-bloggs/')
|
||||
|
||||
self.assertContains(response, "EXTERNAL VIEW: joe-bloggs")
|
||||
|
||||
|
||||
class TestRoutablePageTemplateTag(TestRoutablePage):
|
||||
def setUp(self):
|
||||
super(TestRoutablePageTemplateTag, self).setUp()
|
||||
self.rf = RequestFactory()
|
||||
self.request = self.rf.get(self.routable_page.url)
|
||||
self.request.site = Site.find_for_request(self.request)
|
||||
self.context = {'request': self.request}
|
||||
|
||||
def test_templatetag_reverse_main_view(self):
|
||||
url = routablepageurl(self.context, self.routable_page,
|
||||
'main')
|
||||
self.assertEqual(url, self.routable_page.url)
|
||||
|
||||
def test_templatetag_reverse_archive_by_year_view(self):
|
||||
url = routablepageurl(self.context, self.routable_page,
|
||||
'archive_by_year', '2014')
|
||||
|
||||
self.assertEqual(url, self.routable_page.url + 'archive/year/2014/')
|
||||
|
||||
def test_templatetag_reverse_archive_by_author_view(self):
|
||||
url = routablepageurl(self.context, self.routable_page,
|
||||
'archive_by_author', author_slug='joe-bloggs')
|
||||
|
||||
self.assertEqual(url, self.routable_page.url + 'archive/author/joe-bloggs/')
|
||||
|
||||
def test_templatetag_reverse_external_view(self):
|
||||
url = routablepageurl(self.context, self.routable_page,
|
||||
'external_view', 'joe-bloggs')
|
||||
|
||||
self.assertEqual(url, self.routable_page.url + 'external/joe-bloggs/')
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.contrib.wagtailsitemaps.apps.WagtailSitemapsAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailSitemapsAppConfig(AppConfig):
|
||||
name = 'wagtail.contrib.wagtailsitemaps'
|
||||
label = 'wagtailsitemaps'
|
||||
verbose_name = "Wagtail sitemaps"
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.contrib.wagtailstyleguide.apps.WagtailStyleGuideAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailStyleGuideAppConfig(AppConfig):
|
||||
name = 'wagtail.contrib.wagtailstyleguide'
|
||||
label = 'wagtailstyleguide'
|
||||
verbose_name = "Wagtail style guide"
|
|
@ -30,6 +30,7 @@
|
|||
<li><a href="#editor">Page editor</a></li>
|
||||
<li><a href="#tabs">Tabs</a></li>
|
||||
<li><a href="#breadcrumbs">Breadcrumbs</a></li>
|
||||
<li><a href="#progress">Progress indicators</a></li>
|
||||
<li><a href="#misc">Misc formatters</a></li>
|
||||
<li><a href="#icons">Icons</a></li>
|
||||
</ul>
|
||||
|
@ -406,6 +407,20 @@
|
|||
|
||||
</section>
|
||||
|
||||
<section id="progress">
|
||||
<h2>Progress indicators</h2>
|
||||
|
||||
<div id="progress-example" class="progress active">
|
||||
<div class="bar">60%</div>
|
||||
</div>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<div id="progress-example2" class="progress active">
|
||||
<div class="bar" style="width: 50%;">50%</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="misc">
|
||||
<h2>Misc formatters</h2>
|
||||
<h3>Avatar icons</h3>
|
||||
|
@ -506,7 +521,16 @@
|
|||
{% block extra_js %}
|
||||
<script>
|
||||
$(function(){
|
||||
|
||||
(function runprogress(){
|
||||
var to = setTimeout(function(){
|
||||
runprogress();
|
||||
clearTimeout(to);
|
||||
var to2 = setTimeout(function(){
|
||||
$('#progress-example .bar').css('width', '20%');
|
||||
}, 2000);
|
||||
}, 3000);
|
||||
$('#progress-example .bar').css('width', '80%');
|
||||
})();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,10 @@
|
|||
*.pyc
|
||||
.DS_Store
|
||||
/.venv/
|
||||
/*/settings/local.py
|
||||
/static/
|
||||
/media/
|
||||
/.vagrant/
|
||||
Vagrantfile.local
|
||||
/docs/_build/
|
||||
/db.sqlite3
|
|
@ -0,0 +1,27 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
Vagrant::Config.run do |config|
|
||||
# Base box to build off, and download URL for when it doesn't exist on the user's system already
|
||||
config.vm.box = "wagtail-base-v0.3"
|
||||
config.vm.box_url = "http://downloads.torchbox.com/wagtail-base-v0.3.box"
|
||||
|
||||
# Forward a port from the guest to the host, which allows for outside
|
||||
# computers to access the VM, whereas host only networking does not.
|
||||
config.vm.forward_port 8000, 8111
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# an identifier, the second is the path on the guest to mount the
|
||||
# folder, and the third is the path on the host to the actual folder.
|
||||
config.vm.share_folder "project", "/home/vagrant/{{ project_name }}", "."
|
||||
|
||||
# Enable provisioning with a shell script.
|
||||
config.vm.provision :shell, :path => "vagrant/provision.sh", :args => "{{ project_name }}"
|
||||
|
||||
# If a 'Vagrantfile.local' file exists, import any configuration settings
|
||||
# defined there into here. Vagrantfile.local is ignored in version control,
|
||||
# so this can be used to add configuration specific to this computer.
|
||||
if File.exist? "Vagrantfile.local"
|
||||
instance_eval File.read("Vagrantfile.local"), "Vagrantfile.local"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,87 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'HomePage'
|
||||
db.create_table('core_homepage', (
|
||||
('page_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['wagtailcore.Page'], unique=True, primary_key=True)),
|
||||
))
|
||||
db.send_create_signal('core', ['HomePage'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'HomePage'
|
||||
db.delete_table('core_homepage')
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'core.homepage': {
|
||||
'Meta': {'object_name': 'HomePage', '_ormbases': ['wagtailcore.Page']},
|
||||
'page_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['wagtailcore.Page']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'wagtailcore.page': {
|
||||
'Meta': {'object_name': 'Page'},
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}),
|
||||
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['core']
|
|
@ -0,0 +1,114 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models, connection
|
||||
from django.db.transaction import set_autocommit
|
||||
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
depends_on = (
|
||||
('wagtailcore', '0002_initial_data'),
|
||||
)
|
||||
|
||||
def forwards(self, orm):
|
||||
if connection.vendor == 'sqlite':
|
||||
set_autocommit(True)
|
||||
|
||||
orm['wagtailcore.Page'].objects.get(id=2).delete()
|
||||
|
||||
homepage_content_type, created = orm['contenttypes.contenttype'].objects.get_or_create(
|
||||
model='homepage', app_label='core', defaults={'name': 'Homepage'})
|
||||
|
||||
homepage = orm['core.HomePage'].objects.create(
|
||||
title="Homepage",
|
||||
slug='home',
|
||||
content_type=homepage_content_type,
|
||||
path='00010001',
|
||||
depth=2,
|
||||
numchild=0,
|
||||
url_path='/home/',
|
||||
)
|
||||
|
||||
orm['wagtailcore.site'].objects.create(
|
||||
hostname='localhost', root_page=homepage, is_default_site=True)
|
||||
|
||||
def backwards(self, orm):
|
||||
pass
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'core.homepage': {
|
||||
'Meta': {'object_name': 'HomePage', '_ormbases': ['wagtailcore.Page']},
|
||||
'page_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['wagtailcore.Page']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'wagtailcore.page': {
|
||||
'Meta': {'object_name': 'Page'},
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}),
|
||||
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'wagtailcore.site': {
|
||||
'Meta': {'unique_together': "(('hostname', 'port'),)", 'object_name': 'Site'},
|
||||
'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_default_site': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'port': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
|
||||
'root_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sites_rooted_here'", 'to': "orm['wagtailcore.Page']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['core']
|
||||
symmetrical = True
|
|
@ -0,0 +1,7 @@
|
|||
from django.db import models
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
class HomePage(Page):
|
||||
pass
|
|
@ -0,0 +1,9 @@
|
|||
{% templatetag openblock %} extends "base.html" {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block body_class {% templatetag closeblock %}template-404{% templatetag openblock %} endblock {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block content {% templatetag closeblock %}
|
||||
<h1>Page not found</h1>
|
||||
|
||||
<h2>Sorry, this page could not be found.</h2>
|
||||
{% templatetag openblock %} endblock {% templatetag closeblock %}
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Internal server error</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Internal server error</h1>
|
||||
|
||||
<h2>Sorry, there seems to be an error. Please try again soon.</h2>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
{% templatetag openblock %} load compress static wagtailuserbar {% templatetag closeblock %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>{% templatetag openblock %} block title %}{% templatetag openblock %} if self.seo_title %}{% templatetag openvariable %} self.seo_title {% templatetag closevariable %}{% templatetag openblock %} else %}{% templatetag openvariable %} self.title {% templatetag closevariable %}{% templatetag openblock %} endif {% templatetag closeblock %}{% templatetag openblock %} endblock {% templatetag closeblock %}{% templatetag openblock %} block title_suffix {% templatetag closeblock %}{% templatetag openblock %} endblock {% templatetag closeblock %}</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
{% templatetag openblock %} compress css {% templatetag closeblock %}
|
||||
{# Global stylesheets #}
|
||||
<link rel="stylesheet" type="text/x-scss" href="{% templatetag openblock %} static 'css/{{ project_name }}.scss' {% templatetag closeblock %}">
|
||||
{% templatetag openblock %} endcompress {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block extra_css {% templatetag closeblock %}
|
||||
{# Override this in templates to add extra stylesheets #}
|
||||
{% templatetag openblock %} endblock {% templatetag closeblock %}
|
||||
</head>
|
||||
|
||||
<body class="{% templatetag openblock %} block body_class {% templatetag closeblock %}{% templatetag openblock %} endblock {% templatetag closeblock %}">
|
||||
{% templatetag openblock %} wagtailuserbar {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block content {% templatetag closeblock %}{% templatetag openblock %} endblock {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} compress js {% templatetag closeblock %}
|
||||
{# Global javascript #}
|
||||
<script type="text/javascript" src="{% templatetag openblock %} static 'js/{{ project_name }}.js' {% templatetag closeblock %}"></script>
|
||||
{% templatetag openblock %} endcompress {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block extra_js {% templatetag closeblock %}
|
||||
{# Override this in templates to add extra javascript #}
|
||||
{% templatetag openblock %} endblock {% templatetag closeblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
{% templatetag openblock %} extends "base.html" {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} load static core_tags {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block body_class {% templatetag closeblock %}template-{% templatetag openvariable %} self.get_verbose_name|slugify {% templatetag closevariable %}{% templatetag openblock %} endblock {% templatetag closeblock %}
|
||||
|
||||
{% templatetag openblock %} block content {% templatetag closeblock %}
|
||||
<h1>Welcome to your new Wagtail site!</h1>
|
||||
|
||||
<p>You can access the admin interface <a href="{% templatetag openblock %} url 'wagtailadmin_home' {% templatetag closeblock %}">here</a> (make sure you have run "./manage.py createsuperuser" in the console first).
|
||||
|
||||
<p>If you haven't already given the documentation a read, head over to <a href="http://wagtail.readthedocs.org/">http://wagtail.readthedocs.org</a> to start building on Wagtail</p>
|
||||
{% templatetag openblock %} endblock {% templatetag closeblock %}
|
|
@ -0,0 +1,3 @@
|
|||
from django import template
|
||||
|
||||
register = template.Library()
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
|
@ -0,0 +1 @@
|
|||
from .dev import *
|
|
@ -0,0 +1,164 @@
|
|||
"""
|
||||
Django settings for {{ project_name }} project.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/{{ docs_version }}/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/
|
||||
"""
|
||||
|
||||
from os.path import abspath, dirname, join
|
||||
|
||||
# Absolute filesystem path to the Django project directory:
|
||||
PROJECT_ROOT = dirname(dirname(dirname(abspath(__file__))))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '{{ secret_key }}'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
'south',
|
||||
'compressor',
|
||||
'taggit',
|
||||
'modelcluster',
|
||||
|
||||
'wagtail.wagtailcore',
|
||||
'wagtail.wagtailadmin',
|
||||
'wagtail.wagtaildocs',
|
||||
'wagtail.wagtailsnippets',
|
||||
'wagtail.wagtailusers',
|
||||
'wagtail.wagtailimages',
|
||||
'wagtail.wagtailembeds',
|
||||
'wagtail.wagtailsearch',
|
||||
'wagtail.wagtailredirects',
|
||||
'wagtail.wagtailforms',
|
||||
|
||||
'core',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
|
||||
'wagtail.wagtailcore.middleware.SiteMiddleware',
|
||||
'wagtail.wagtailredirects.middleware.RedirectMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = '{{ project_name }}.urls'
|
||||
WSGI_APPLICATION = '{{ project_name }}.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#databases
|
||||
|
||||
# SQLite (simplest install)
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': join(PROJECT_ROOT, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
# PostgreSQL (Recommended, but requires the psycopg2 library and Postgresql development headers)
|
||||
# DATABASES = {
|
||||
# 'default': {
|
||||
# 'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
# 'NAME': '{{ project_name }}',
|
||||
# 'USER': 'postgres',
|
||||
# 'PASSWORD': '',
|
||||
# 'HOST': '', # Set to empty string for localhost.
|
||||
# 'PORT': '', # Set to empty string for default.
|
||||
# 'CONN_MAX_AGE': 600, # number of seconds database connections should persist for
|
||||
# }
|
||||
# }
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/{{ docs_version }}/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-gb'
|
||||
TIME_ZONE = 'UTC'
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/{{ docs_version }}/howto/static-files/
|
||||
|
||||
STATIC_ROOT = join(PROJECT_ROOT, 'static')
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
MEDIA_ROOT = join(PROJECT_ROOT, 'media')
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
|
||||
# Django compressor settings
|
||||
# http://django-compressor.readthedocs.org/en/latest/settings/
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/x-scss', 'django_libsass.SassCompiler'),
|
||||
)
|
||||
|
||||
|
||||
# Template configuration
|
||||
|
||||
from django.conf import global_settings
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
|
||||
'django.core.context_processors.request',
|
||||
)
|
||||
|
||||
|
||||
# Wagtail settings
|
||||
|
||||
LOGIN_URL = 'wagtailadmin_login'
|
||||
LOGIN_REDIRECT_URL = 'wagtailadmin_home'
|
||||
|
||||
WAGTAIL_SITE_NAME = "{{ project_name }}"
|
||||
|
||||
# Use Elasticsearch as the search backend for extra performance and better search results:
|
||||
# http://wagtail.readthedocs.org/en/latest/howto/performance.html#search
|
||||
# http://wagtail.readthedocs.org/en/latest/core_components/search/backends.html#elasticsearch-backend
|
||||
#
|
||||
# WAGTAILSEARCH_BACKENDS = {
|
||||
# 'default': {
|
||||
# 'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
|
||||
# 'INDEX': '{{ project_name }}',
|
||||
# },
|
||||
# }
|
||||
|
||||
|
||||
# Whether to use face/feature detection to improve image cropping - requires OpenCV
|
||||
WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = False
|
|
@ -0,0 +1,13 @@
|
|||
from .base import *
|
||||
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
||||
|
||||
try:
|
||||
from .local import *
|
||||
except ImportError:
|
||||
pass
|
|
@ -0,0 +1,48 @@
|
|||
from .base import *
|
||||
|
||||
|
||||
# Disable debug mode
|
||||
|
||||
DEBUG = False
|
||||
TEMPLATE_DEBUG = False
|
||||
|
||||
|
||||
# Compress static files offline
|
||||
# http://django-compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE
|
||||
|
||||
COMPRESS_OFFLINE = True
|
||||
|
||||
|
||||
# Send notification emails as a background task using Celery,
|
||||
# to prevent this from blocking web server threads
|
||||
# (requires the django-celery package):
|
||||
# http://celery.readthedocs.org/en/latest/configuration.html
|
||||
|
||||
# import djcelery
|
||||
#
|
||||
# djcelery.setup_loader()
|
||||
#
|
||||
# CELERY_SEND_TASK_ERROR_EMAILS = True
|
||||
# BROKER_URL = 'redis://'
|
||||
|
||||
|
||||
# Use Redis as the cache backend for extra performance
|
||||
# (requires the django-redis-cache package):
|
||||
# http://wagtail.readthedocs.org/en/latest/howto/performance.html#cache
|
||||
|
||||
# CACHES = {
|
||||
# 'default': {
|
||||
# 'BACKEND': 'redis_cache.cache.RedisCache',
|
||||
# 'LOCATION': '127.0.0.1:6379',
|
||||
# 'KEY_PREFIX': '{{ project_name }}',
|
||||
# 'OPTIONS': {
|
||||
# 'CLIENT_CLASS': 'redis_cache.client.DefaultClient',
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
|
||||
try:
|
||||
from .local import *
|
||||
except ImportError:
|
||||
pass
|
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
|
||||
from django.conf.urls import patterns, include, url
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
|
||||
from wagtail.wagtailadmin import urls as wagtailadmin_urls
|
||||
from wagtail.wagtailsearch import urls as wagtailsearch_urls
|
||||
from wagtail.wagtaildocs import urls as wagtaildocs_urls
|
||||
from wagtail.wagtailcore import urls as wagtail_urls
|
||||
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
|
||||
# Register search signal handlers
|
||||
from wagtail.wagtailsearch.signal_handlers import register_signal_handlers as wagtailsearch_register_signal_handlers
|
||||
wagtailsearch_register_signal_handlers()
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^django-admin/', include(admin.site.urls)),
|
||||
|
||||
url(r'^admin/', include(wagtailadmin_urls)),
|
||||
url(r'^search/', include(wagtailsearch_urls)),
|
||||
url(r'^documents/', include(wagtaildocs_urls)),
|
||||
|
||||
url(r'', include(wagtail_urls)),
|
||||
)
|
||||
|
||||
|
||||
if settings.DEBUG:
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
|
||||
urlpatterns += staticfiles_urlpatterns()
|
||||
urlpatterns += static(settings.MEDIA_URL + 'images/', document_root=os.path.join(settings.MEDIA_ROOT, 'images'))
|
|
@ -0,0 +1,14 @@
|
|||
"""
|
||||
WSGI config for {{ project_name }} project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings.production")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
|
@ -0,0 +1,3 @@
|
|||
==================
|
||||
{{ project_name }}
|
||||
==================
|
|
@ -0,0 +1,12 @@
|
|||
# Minimal requirements
|
||||
Django>=1.6.2,<1.7
|
||||
South==1.0.0
|
||||
wagtail==0.6
|
||||
|
||||
# Recommended components (require additional setup):
|
||||
# psycopg2==2.5.2
|
||||
# elasticsearch==1.1.1
|
||||
|
||||
# Recommended components to improve performance in production:
|
||||
# django-redis-cache==0.13.0
|
||||
# django-celery==3.1.10
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
PROJECT_NAME=$1
|
||||
|
||||
PROJECT_DIR=/home/vagrant/$PROJECT_NAME
|
||||
VIRTUALENV_DIR=/home/vagrant/.virtualenvs/$PROJECT_NAME
|
||||
|
||||
PYTHON=$VIRTUALENV_DIR/bin/python
|
||||
PIP=$VIRTUALENV_DIR/bin/pip
|
||||
|
||||
|
||||
# Virtualenv setup for project
|
||||
su - vagrant -c "/usr/local/bin/virtualenv --system-site-packages $VIRTUALENV_DIR && \
|
||||
echo $PROJECT_DIR > $VIRTUALENV_DIR/.project && \
|
||||
PIP_DOWNLOAD_CACHE=/home/vagrant/.pip_download_cache $PIP install -r $PROJECT_DIR/requirements.txt"
|
||||
|
||||
echo "workon $PROJECT_NAME" >> /home/vagrant/.bashrc
|
||||
|
||||
|
||||
# Set execute permissions on manage.py as they get lost if we build from a zip file
|
||||
chmod a+x $PROJECT_DIR/manage.py
|
||||
|
||||
|
||||
# Run syncdb/migrate/update_index
|
||||
su - vagrant -c "$PYTHON $PROJECT_DIR/manage.py syncdb --noinput && \
|
||||
$PYTHON $PROJECT_DIR/manage.py migrate --noinput && \
|
||||
$PYTHON $PROJECT_DIR/manage.py update_index"
|
||||
|
||||
|
||||
# Add a couple of aliases to manage.py into .bashrc
|
||||
cat << EOF >> /home/vagrant/.bashrc
|
||||
alias dj="$PYTHON $PROJECT_DIR/manage.py"
|
||||
alias djrun="dj runserver 0.0.0.0:8000"
|
||||
EOF
|
|
@ -90,8 +90,8 @@
|
|||
"model": "tests.eventpagespeaker",
|
||||
"fields": {
|
||||
"page": 4,
|
||||
"first_name": "Santa",
|
||||
"last_name": "Claus",
|
||||
"first_name": "Father",
|
||||
"last_name": "Christmas",
|
||||
"sort_order": 0
|
||||
}
|
||||
},
|
||||
|
@ -567,7 +567,17 @@
|
|||
"model": "tests.AdvertPlacement",
|
||||
"fields": {
|
||||
"page": 2,
|
||||
"advert": 1
|
||||
"advert": 1,
|
||||
"colour": "yellow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "tests.AdvertPlacement",
|
||||
"fields": {
|
||||
"page": 4,
|
||||
"advert": 1,
|
||||
"colour": "greener than a Christmas tree"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CustomUser',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last login')),
|
||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('username', models.CharField(unique=True, max_length=100)),
|
||||
('email', models.EmailField(max_length=255, blank=True)),
|
||||
('is_staff', models.BooleanField(default=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('first_name', models.CharField(max_length=50, blank=True)),
|
||||
('last_name', models.CharField(max_length=50, blank=True)),
|
||||
('groups', models.ManyToManyField(to='auth.Group', verbose_name='groups', blank=True)),
|
||||
('user_permissions', models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', blank=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,386 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
import modelcluster.fields
|
||||
import wagtail.contrib.wagtailroutablepage.models
|
||||
import wagtail.wagtailcore.fields
|
||||
import wagtail.wagtailsearch.index
|
||||
import modelcluster.tags
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wagtailcore', '0002_initial_data'),
|
||||
('wagtaildocs', '0002_initial_data'),
|
||||
('taggit', '0001_initial'),
|
||||
('wagtailimages', '0002_initial_data'),
|
||||
('tests', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Advert',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('url', models.URLField(null=True, blank=True)),
|
||||
('text', models.CharField(max_length=255)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AdvertPlacement',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('advert', models.ForeignKey(to='tests.Advert', related_name='+')),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AlphaSnippet',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('text', models.CharField(max_length=255)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BusinessChild',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BusinessIndex',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BusinessSubIndex',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventIndex',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
('date_from', models.DateField(null=True, verbose_name='Start date')),
|
||||
('date_to', models.DateField(null=True, help_text='Not required if event is on a single day', blank=True, verbose_name='End date')),
|
||||
('time_from', models.TimeField(null=True, blank=True, verbose_name='Start time')),
|
||||
('time_to', models.TimeField(null=True, blank=True, verbose_name='End time')),
|
||||
('audience', models.CharField(choices=[('public', 'Public'), ('private', 'Private')], max_length=255)),
|
||||
('location', models.CharField(max_length=255)),
|
||||
('body', wagtail.wagtailcore.fields.RichTextField(blank=True)),
|
||||
('cost', models.CharField(max_length=255)),
|
||||
('signup_link', models.URLField(blank=True)),
|
||||
('feed_image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventPageCarouselItem',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('sort_order', models.IntegerField(null=True, blank=True, editable=False)),
|
||||
('link_external', models.URLField(blank=True, verbose_name='External link')),
|
||||
('embed_url', models.URLField(blank=True, verbose_name='Embed URL')),
|
||||
('caption', models.CharField(blank=True, max_length=255)),
|
||||
('image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)),
|
||||
('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'ordering': ['sort_order'],
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventPageRelatedLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('sort_order', models.IntegerField(null=True, blank=True, editable=False)),
|
||||
('link_external', models.URLField(blank=True, verbose_name='External link')),
|
||||
('title', models.CharField(help_text='Link title', max_length=255)),
|
||||
('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'ordering': ['sort_order'],
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventPageSpeaker',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('sort_order', models.IntegerField(null=True, blank=True, editable=False)),
|
||||
('link_external', models.URLField(blank=True, verbose_name='External link')),
|
||||
('first_name', models.CharField(blank=True, verbose_name='Name', max_length=255)),
|
||||
('last_name', models.CharField(blank=True, verbose_name='Surname', max_length=255)),
|
||||
('image', models.ForeignKey(related_name='+', blank=True, to='wagtailimages.Image', on_delete=django.db.models.deletion.SET_NULL, null=True)),
|
||||
('link_document', models.ForeignKey(related_name='+', blank=True, to='wagtaildocs.Document', null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'ordering': ['sort_order'],
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FormField',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('sort_order', models.IntegerField(null=True, blank=True, editable=False)),
|
||||
('label', models.CharField(help_text='The label of the form field', max_length=255)),
|
||||
('field_type', models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16)),
|
||||
('required', models.BooleanField(default=True)),
|
||||
('choices', models.CharField(blank=True, help_text='Comma seperated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512)),
|
||||
('default_value', models.CharField(blank=True, help_text='Default value. Comma seperated values supported for checkboxes.', max_length=255)),
|
||||
('help_text', models.CharField(blank=True, max_length=255)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'ordering': ['sort_order'],
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FormPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
('to_address', models.CharField(blank=True, help_text='Optional - form submissions will be emailed to this address', max_length=255)),
|
||||
('from_address', models.CharField(blank=True, max_length=255)),
|
||||
('subject', models.CharField(blank=True, max_length=255)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PageWithOldStyleRouteMethod',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
('content', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RoutablePageTest',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=(wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin, 'wagtailcore.page'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SearchTest',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('title', models.CharField(max_length=255)),
|
||||
('content', models.TextField()),
|
||||
('live', models.BooleanField(default=False)),
|
||||
('published_date', models.DateField(null=True)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model, wagtail.wagtailsearch.index.Indexed),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SearchTestChild',
|
||||
fields=[
|
||||
('searchtest_ptr', models.OneToOneField(parent_link=True, to='tests.SearchTest', serialize=False, auto_created=True, primary_key=True)),
|
||||
('subtitle', models.CharField(null=True, blank=True, max_length=255)),
|
||||
('extra_content', models.TextField()),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=('tests.searchtest',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SearchTestOldConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model, wagtail.wagtailsearch.index.Indexed),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SearchTestOldConfigList',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model, wagtail.wagtailsearch.index.Indexed),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SimplePage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
('content', models.TextField()),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StandardChild',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StandardIndex',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TaggedPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TaggedPageTag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('content_object', modelcluster.fields.ParentalKey(to='tests.TaggedPage', related_name='tagged_items')),
|
||||
('tag', models.ForeignKey(to='taggit.Tag', related_name='tests_taggedpagetag_items')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ZuluSnippet',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('text', models.CharField(max_length=255)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='taggedpage',
|
||||
name='tags',
|
||||
field=modelcluster.tags.ClusterTaggableManager(through='tests.TaggedPageTag', blank=True, verbose_name='Tags', to='taggit.Tag', help_text='A comma-separated list of tags.'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='formfield',
|
||||
name='page',
|
||||
field=modelcluster.fields.ParentalKey(to='tests.FormPage', related_name='form_fields'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagespeaker',
|
||||
name='link_page',
|
||||
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagespeaker',
|
||||
name='page',
|
||||
field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='speakers'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagerelatedlink',
|
||||
name='link_page',
|
||||
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagerelatedlink',
|
||||
name='page',
|
||||
field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='related_links'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagecarouselitem',
|
||||
name='link_page',
|
||||
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventpagecarouselitem',
|
||||
name='page',
|
||||
field=modelcluster.fields.ParentalKey(to='tests.EventPage', related_name='carousel_items'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='advertplacement',
|
||||
name='page',
|
||||
field=modelcluster.fields.ParentalKey(to='wagtailcore.Page', related_name='advert_placements'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(related_name='user_set', blank=True, verbose_name='groups', to='auth.Group', related_query_name='user', help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='user_permissions',
|
||||
field=models.ManyToManyField(related_name='user_set', blank=True, verbose_name='user permissions', to='auth.Permission', related_query_name='user', help_text='Specific permissions for this user.'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tests', '0002_auto_20140827_0908'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='advertplacement',
|
||||
name='colour',
|
||||
field=models.CharField(default='blue', max_length=255),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -17,7 +17,7 @@ from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
|
|||
from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel
|
||||
from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
|
||||
from wagtail.wagtailsnippets.models import register_snippet
|
||||
from wagtail.wagtailsearch import indexed
|
||||
from wagtail.wagtailsearch import index
|
||||
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
|
||||
|
||||
|
||||
|
@ -228,8 +228,11 @@ class EventPage(Page):
|
|||
related_name='+'
|
||||
)
|
||||
|
||||
indexed_fields = ('get_audience_display', 'location', 'body')
|
||||
search_name = "Event"
|
||||
search_fields = (
|
||||
index.SearchField('get_audience_display'),
|
||||
index.SearchField('location'),
|
||||
index.SearchField('body'),
|
||||
)
|
||||
|
||||
password_required_template = 'tests/event_page_password_required.html'
|
||||
|
||||
|
@ -330,6 +333,7 @@ FormPage.content_panels = [
|
|||
class AdvertPlacement(models.Model):
|
||||
page = ParentalKey('wagtailcore.Page', related_name='advert_placements')
|
||||
advert = models.ForeignKey('tests.Advert', related_name='+')
|
||||
colour = models.CharField(max_length=255)
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Advert(models.Model):
|
||||
|
@ -372,34 +376,50 @@ class ZuluSnippet(models.Model):
|
|||
|
||||
|
||||
class StandardIndex(Page):
|
||||
pass
|
||||
""" Index for the site, not allowed to be placed anywhere """
|
||||
parent_page_types = []
|
||||
|
||||
|
||||
StandardIndex.content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
InlinePanel(StandardIndex, 'advert_placements', label="Adverts"),
|
||||
]
|
||||
|
||||
|
||||
class StandardChild(Page):
|
||||
pass
|
||||
|
||||
|
||||
class BusinessIndex(Page):
|
||||
""" Can be placed anywhere, can only have Business children """
|
||||
subpage_types = ['tests.BusinessChild', 'tests.BusinessSubIndex']
|
||||
|
||||
|
||||
class BusinessSubIndex(Page):
|
||||
""" Can be placed under BusinessIndex, and have BusinessChild children """
|
||||
subpage_types = ['tests.BusinessChild']
|
||||
parent_page_types = ['tests.BusinessIndex']
|
||||
|
||||
|
||||
class BusinessChild(Page):
|
||||
""" Can only be placed under Business indexes, no children allowed """
|
||||
subpage_types = []
|
||||
parent_page_types = ['tests.BusinessIndex', BusinessSubIndex]
|
||||
|
||||
|
||||
class SearchTest(models.Model, indexed.Indexed):
|
||||
class SearchTest(models.Model, index.Indexed):
|
||||
title = models.CharField(max_length=255)
|
||||
content = models.TextField()
|
||||
live = models.BooleanField(default=False)
|
||||
published_date = models.DateField(null=True)
|
||||
|
||||
search_fields = [
|
||||
indexed.SearchField('title', partial_match=True),
|
||||
indexed.SearchField('content'),
|
||||
indexed.SearchField('callable_indexed_field'),
|
||||
indexed.FilterField('title'),
|
||||
indexed.FilterField('live'),
|
||||
indexed.FilterField('published_date'),
|
||||
index.SearchField('title', partial_match=True),
|
||||
index.SearchField('content'),
|
||||
index.SearchField('callable_indexed_field'),
|
||||
index.FilterField('title'),
|
||||
index.FilterField('live'),
|
||||
index.FilterField('published_date'),
|
||||
]
|
||||
|
||||
def callable_indexed_field(self):
|
||||
|
@ -411,40 +431,11 @@ class SearchTestChild(SearchTest):
|
|||
extra_content = models.TextField()
|
||||
|
||||
search_fields = SearchTest.search_fields + [
|
||||
indexed.SearchField('subtitle', partial_match=True),
|
||||
indexed.SearchField('extra_content'),
|
||||
index.SearchField('subtitle', partial_match=True),
|
||||
index.SearchField('extra_content'),
|
||||
]
|
||||
|
||||
|
||||
class SearchTestOldConfig(models.Model, indexed.Indexed):
|
||||
"""
|
||||
This tests that the Indexed class can correctly handle models that
|
||||
use the old "indexed_fields" configuration format.
|
||||
"""
|
||||
indexed_fields = {
|
||||
# A search field with predictive search and boosting
|
||||
'title': {
|
||||
'type': 'string',
|
||||
'analyzer': 'edgengram_analyzer',
|
||||
'boost': 100,
|
||||
},
|
||||
|
||||
# A filter field
|
||||
'live': {
|
||||
'type': 'boolean',
|
||||
'index': 'not_analyzed',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class SearchTestOldConfigList(models.Model, indexed.Indexed):
|
||||
"""
|
||||
This tests that the Indexed class can correctly handle models that
|
||||
use the old "indexed_fields" configuration format using a list.
|
||||
"""
|
||||
indexed_fields = ['title', 'content']
|
||||
|
||||
|
||||
def routable_page_external_view(request, arg):
|
||||
return HttpResponse("EXTERNAL VIEW: " + arg)
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
"""An alternative urlconf module where Wagtail front-end URLs
|
||||
are rooted at '/site/' rather than '/'"""
|
||||
|
||||
from django.conf.urls import patterns, include, url
|
||||
|
||||
from wagtail.wagtailcore import urls as wagtail_urls
|
||||
from wagtail.wagtailadmin import urls as wagtailadmin_urls
|
||||
from wagtail.wagtaildocs import urls as wagtaildocs_urls
|
||||
from wagtail.wagtailimages import urls as wagtailimages_urls
|
||||
from wagtail.wagtailsearch import urls as wagtailsearch_urls
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^admin/', include(wagtailadmin_urls)),
|
||||
url(r'^search/', include(wagtailsearch_urls)),
|
||||
url(r'^documents/', include(wagtaildocs_urls)),
|
||||
url(r'^images/', include(wagtailimages_urls)),
|
||||
url(r'^site/', include(wagtail_urls)),
|
||||
)
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
|
||||
import django
|
||||
from django.conf import global_settings
|
||||
|
||||
|
||||
|
@ -57,7 +58,6 @@ INSTALLED_APPS = [
|
|||
'django.contrib.admin',
|
||||
|
||||
'taggit',
|
||||
'south',
|
||||
'compressor',
|
||||
|
||||
'wagtail.wagtailcore',
|
||||
|
@ -68,7 +68,6 @@ INSTALLED_APPS = [
|
|||
'wagtail.wagtailimages',
|
||||
'wagtail.wagtailembeds',
|
||||
'wagtail.wagtailsearch',
|
||||
'wagtail.wagtailredirects',
|
||||
'wagtail.wagtailforms',
|
||||
'wagtail.contrib.wagtailstyleguide',
|
||||
'wagtail.contrib.wagtailsitemaps',
|
||||
|
@ -76,6 +75,27 @@ INSTALLED_APPS = [
|
|||
'wagtail.tests',
|
||||
]
|
||||
|
||||
# If we are using Django 1.6, add South to INSTALLED_APPS
|
||||
if django.VERSION < (1, 7):
|
||||
INSTALLED_APPS.append('south')
|
||||
|
||||
|
||||
# If we are using Django 1.7 install wagtailredirects with its appconfig
|
||||
# Theres nothing special about wagtailredirects, we just need to have one
|
||||
# app which uses AppConfigs to test that hooks load properly
|
||||
|
||||
if django.VERSION < (1, 7):
|
||||
INSTALLED_APPS.append('wagtail.wagtailredirects')
|
||||
else:
|
||||
INSTALLED_APPS.append('wagtail.wagtailredirects.apps.WagtailRedirectsAppConfig')
|
||||
|
||||
# As we don't have south migrations for tests, South thinks
|
||||
# the Django 1.7 migrations are South migrations.
|
||||
SOUTH_MIGRATION_MODULES = {
|
||||
'tests': 'ignore',
|
||||
}
|
||||
|
||||
|
||||
# Using DatabaseCache to make sure that the cache is cleared between tests.
|
||||
# This prevents false-positives in some wagtail core tests where we are
|
||||
# changing the 'wagtail_root_paths' key which may cause future tests to fail.
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.http import HttpResponse
|
|||
|
||||
from wagtail.wagtailcore import hooks
|
||||
from wagtail.wagtailcore.whitelist import attribute_rule, check_url, allow_without_attributes
|
||||
from wagtail.wagtailadmin.menu import MenuItem
|
||||
|
||||
|
||||
# Register one hook using decorators...
|
||||
|
@ -28,3 +29,12 @@ def block_googlebot(page, request, serve_args, serve_kwargs):
|
|||
if request.META.get('HTTP_USER_AGENT') == 'GoogleBot':
|
||||
return HttpResponse("<h1>bad googlebot no cookie</h1>")
|
||||
hooks.register('before_serve_page', block_googlebot)
|
||||
|
||||
|
||||
class KittensMenuItem(MenuItem):
|
||||
def is_shown(self, request):
|
||||
return not request.GET.get('hide-kittens', False)
|
||||
|
||||
@hooks.register('register_admin_menu_item')
|
||||
def register_kittens_menu_item():
|
||||
return KittensMenuItem('Kittens!', 'http://www.tomroyal.com/teaandkittens/', classnames='icon icon-kitten', attrs={'data-fluffy': 'yes'}, order=10000)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
try:
|
||||
from importlib import import_module
|
||||
except ImportError:
|
||||
# for Python 2.6, fall back on django.utils.importlib (deprecated as of Django 1.7)
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
import django
|
||||
from django.conf import settings
|
||||
from django.utils.module_loading import module_has_submodule
|
||||
|
||||
|
||||
def get_app_modules():
|
||||
"""
|
||||
Generator function that yields a module object for each installed app
|
||||
yields tuples of (app_name, module)
|
||||
"""
|
||||
if django.VERSION < (1, 7):
|
||||
# Django 1.6
|
||||
for app in settings.INSTALLED_APPS:
|
||||
yield app, import_module(app)
|
||||
else:
|
||||
# Django 1.7+
|
||||
from django.apps import apps
|
||||
for app in apps.get_app_configs():
|
||||
yield app.name, app.module
|
||||
|
||||
|
||||
def get_app_submodules(submodule_name):
|
||||
"""
|
||||
Searches each app module for the specified submodule
|
||||
yields tuples of (app_name, module)
|
||||
"""
|
||||
for name, module in get_app_modules():
|
||||
if module_has_submodule(module, submodule_name):
|
||||
yield name, import_module('%s.%s' % (name, submodule_name))
|
|
@ -1,6 +1,6 @@
|
|||
class RemovedInWagtail06Warning(DeprecationWarning):
|
||||
class RemovedInWagtail07Warning(DeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInWagtail07Warning(PendingDeprecationWarning):
|
||||
class RemovedInWagtail08Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'wagtail.wagtailadmin.apps.WagtailAdminAppConfig'
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WagtailAdminAppConfig(AppConfig):
|
||||
name = 'wagtail.wagtailadmin'
|
||||
label = 'wagtailadmin'
|
||||
verbose_name = "Wagtail admin"
|
|
@ -19,8 +19,8 @@ from django.core.urlresolvers import reverse
|
|||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.wagtailcore.utils import camelcase_to_underscore
|
||||
from wagtail.wagtailcore.fields import RichTextArea
|
||||
from wagtail.wagtailcore.utils import camelcase_to_underscore, resolve_model_string
|
||||
|
||||
|
||||
FORM_FIELD_OVERRIDES = {}
|
||||
|
@ -483,21 +483,16 @@ class BasePageChooserPanel(BaseChooserPanel):
|
|||
def target_content_type(cls):
|
||||
if cls._target_content_type is None:
|
||||
if cls.page_type:
|
||||
if isinstance(cls.page_type, string_types):
|
||||
# translate the passed model name into an actual model class
|
||||
from django.db.models import get_model
|
||||
try:
|
||||
app_label, model_name = cls.page_type.split('.')
|
||||
except ValueError:
|
||||
raise ImproperlyConfigured("The page_type passed to PageChooserPanel must be of the form 'app_label.model_name'")
|
||||
try:
|
||||
model = resolve_model_string(cls.page_type)
|
||||
except LookupError:
|
||||
raise ImproperlyConfigured("{0}.page_type must be of the form 'app_label.model_name', given {1!r}".format(
|
||||
cls.__name__, cls.page_type))
|
||||
except ValueError:
|
||||
raise ImproperlyConfigured("{0}.page_type refers to model {1!r} that has not been installed".format(
|
||||
cls.__name__, cls.page_type))
|
||||
|
||||
page_type = get_model(app_label, model_name)
|
||||
if page_type is None:
|
||||
raise ImproperlyConfigured("PageChooserPanel refers to model '%s' that has not been installed" % cls.page_type)
|
||||
else:
|
||||
page_type = cls.page_type
|
||||
|
||||
cls._target_content_type = ContentType.objects.get_for_model(page_type)
|
||||
cls._target_content_type = ContentType.objects.get_for_model(model)
|
||||
else:
|
||||
# TODO: infer the content type by introspection on the foreign key
|
||||
cls._target_content_type = ContentType.objects.get_by_natural_key('wagtailcore', 'page')
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# The 'hooks' module is now part of wagtailcore.
|
||||
# Imports are provided here for backwards compatibility
|
||||
|
||||
import warnings
|
||||
|
||||
from wagtail.utils.deprecation import RemovedInWagtail06Warning
|
||||
|
||||
|
||||
warnings.warn(
|
||||
"The wagtail.wagtailadmin.hooks module has been moved. "
|
||||
"Use wagtail.wagtailcore.hooks instead.", RemovedInWagtail06Warning)
|
||||
|
||||
|
||||
from wagtail.wagtailcore.hooks import register, get_hooks
|
Plik binarny nie jest wyświetlany.
|
@ -1,7 +1,7 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Lyuboslav Petrov <petrov.lyuboslav@gmail.com>, 2014
|
||||
# Lyuboslav Petrov <petrov.lyuboslav@gmail.com>, 2014
|
||||
|
@ -9,21 +9,22 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: Wagtail\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-08-01 16:38+0100\n"
|
||||
"POT-Creation-Date: 2014-09-11 16:37+0100\n"
|
||||
"PO-Revision-Date: 2014-08-01 15:43+0000\n"
|
||||
"Last-Translator: Karl Hobley <karl@torchbox.com>\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/projects/p/wagtail/language/bg/)\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/projects/p/wagtail/"
|
||||
"language/bg/)\n"
|
||||
"Language: bg\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: bg\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: edit_handlers.py:627
|
||||
#: edit_handlers.py:631
|
||||
msgid "Scheduled publishing"
|
||||
msgstr ""
|
||||
|
||||
#: edit_handlers.py:641
|
||||
#: edit_handlers.py:645
|
||||
msgid "Common page configuration"
|
||||
msgstr ""
|
||||
|
||||
|
@ -51,7 +52,9 @@ msgstr "Моля въведете вашият имейл адрес."
|
|||
msgid ""
|
||||
"Sorry, you cannot reset your password here as your user account is managed "
|
||||
"by another server."
|
||||
msgstr "Не можете да възстановите паролата си тук, понеже акаунта ви се менижира от друг сървър."
|
||||
msgstr ""
|
||||
"Не можете да възстановите паролата си тук, понеже акаунта ви се менижира от "
|
||||
"друг сървър."
|
||||
|
||||
#: forms.py:76
|
||||
msgid "This email address is not recognised."
|
||||
|
@ -99,7 +102,7 @@ msgid_plural ""
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: forms.py:124 views/pages.py:155 views/pages.py:272
|
||||
#: forms.py:124 views/pages.py:153 views/pages.py:270
|
||||
msgid "This slug is already in use"
|
||||
msgstr "Този слъг е вече в употреба"
|
||||
|
||||
|
@ -116,6 +119,16 @@ msgstr ""
|
|||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: wagtail_hooks.py:15 templates/wagtailadmin/chooser/_search_results.html:12
|
||||
msgid "Explorer"
|
||||
msgstr "Файлов мениджър"
|
||||
|
||||
#: wagtail_hooks.py:23 templates/wagtailadmin/chooser/_search_form.html:7
|
||||
#: templates/wagtailadmin/pages/search.html:3
|
||||
#: templates/wagtailadmin/pages/search.html:16
|
||||
msgid "Search"
|
||||
msgstr "Търсене"
|
||||
|
||||
#: templates/wagtailadmin/base.html:7 templates/wagtailadmin/home.html:4
|
||||
msgid "Dashboard"
|
||||
msgstr "Работно Табло"
|
||||
|
@ -133,7 +146,9 @@ msgstr "Добре дошъл в %(site_name)s Wagtail CMS"
|
|||
msgid ""
|
||||
"This is your dashboard on which helpful information about content you've "
|
||||
"created will be displayed."
|
||||
msgstr "Това е вашето работно табло, където ще бъде показана полезна информация за контент, който сте създали."
|
||||
msgstr ""
|
||||
"Това е вашето работно табло, където ще бъде показана полезна информация за "
|
||||
"контент, който сте създали."
|
||||
|
||||
#: templates/wagtailadmin/login.html:4 templates/wagtailadmin/login.html:59
|
||||
msgid "Sign in"
|
||||
|
@ -165,7 +180,10 @@ msgid ""
|
|||
"Your avatar image is provided by Gravatar and is connected to your email "
|
||||
"address. With a Gravatar account you can set an avatar for any number of "
|
||||
"other email addresses you use."
|
||||
msgstr "Снимката за вашият Аватар е предоставена от Gravatar и е свързана с вашия имейл адрес. Със сметка в Gravatar можете да зададете аватар за произволен брой други имейл адреси, които използвате."
|
||||
msgstr ""
|
||||
"Снимката за вашият Аватар е предоставена от Gravatar и е свързана с вашия "
|
||||
"имейл адрес. Със сметка в Gravatar можете да зададете аватар за произволен "
|
||||
"брой други имейл адреси, които използвате."
|
||||
|
||||
#: templates/wagtailadmin/account/account.html:25
|
||||
#: templates/wagtailadmin/account/change_password.html:4
|
||||
|
@ -192,7 +210,9 @@ msgstr "Смени парола"
|
|||
#: templates/wagtailadmin/account/change_password.html:21
|
||||
msgid ""
|
||||
"Your password can't be changed here. Please contact a site administrator."
|
||||
msgstr "Вашата парола не може да бъде променена тук. Моля свържете се с администратора на сайта."
|
||||
msgstr ""
|
||||
"Вашата парола не може да бъде променена тук. Моля свържете се с "
|
||||
"администратора на сайта."
|
||||
|
||||
#: templates/wagtailadmin/account/notification_preferences.html:4
|
||||
#: templates/wagtailadmin/account/notification_preferences.html:6
|
||||
|
@ -263,19 +283,16 @@ msgstr "Външен линк"
|
|||
msgid "Email link"
|
||||
msgstr "Имейл линк"
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_form.html:7
|
||||
#: templates/wagtailadmin/pages/search.html:3
|
||||
#: templates/wagtailadmin/pages/search.html:16
|
||||
#: templatetags/wagtailadmin_tags.py:36
|
||||
msgid "Search"
|
||||
msgstr "Търсене"
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:5
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Only pages of type \"%(type)s\" may be chosen for this field. "
|
||||
"Search results will exclude pages of other types.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:3
|
||||
#: templatetags/wagtailadmin_tags.py:35
|
||||
msgid "Explorer"
|
||||
msgstr "Файлов мениджър"
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:8
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:16
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
@ -285,10 +302,19 @@ msgid_plural ""
|
|||
"\n"
|
||||
" There are %(counter)s matches\n"
|
||||
" "
|
||||
msgstr[0] "\nИма едно съвпадение"
|
||||
msgstr[1] "\nИма %(counter)s съвпадения"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"Има едно съвпадение"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"Има %(counter)s съвпадения"
|
||||
|
||||
#: templates/wagtailadmin/chooser/browse.html:2
|
||||
#: templates/wagtailadmin/chooser/browse.html:3
|
||||
#, fuzzy
|
||||
msgid "Choose"
|
||||
msgstr "Изберете страница"
|
||||
|
||||
#: templates/wagtailadmin/chooser/browse.html:6
|
||||
#: templates/wagtailadmin/chooser/search.html:2
|
||||
#: templates/wagtailadmin/edit_handlers/page_chooser_panel.html:13
|
||||
msgid "Choose a page"
|
||||
|
@ -443,8 +469,14 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_pages)s</span> Pages\n"
|
||||
" "
|
||||
msgstr[0] "\n <span>%(total_pages)s</span> Страница\n "
|
||||
msgstr[1] "\n <span>%(total_pages)s</span> Страници\n "
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
" <span>%(total_pages)s</span> Страница\n"
|
||||
" "
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
" <span>%(total_pages)s</span> Страници\n"
|
||||
" "
|
||||
|
||||
#: templates/wagtailadmin/home/site_summary.html:16
|
||||
#, python-format
|
||||
|
@ -456,8 +488,12 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_images)s</span> Images\n"
|
||||
" "
|
||||
msgstr[0] "\n<span>%(total_images)s</span> Изображение"
|
||||
msgstr[1] "\n<span>%(total_images)s</span> Изображения"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"<span>%(total_images)s</span> Изображение"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"<span>%(total_images)s</span> Изображения"
|
||||
|
||||
#: templates/wagtailadmin/home/site_summary.html:25
|
||||
#, python-format
|
||||
|
@ -469,8 +505,12 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_docs)s</span> Documents\n"
|
||||
" "
|
||||
msgstr[0] "\n<span>%(total_docs)s</span> Документ"
|
||||
msgstr[1] "\n<span>%(total_docs)s</span> Документи"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"<span>%(total_docs)s</span> Документ"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"<span>%(total_docs)s</span> Документи"
|
||||
|
||||
#: templates/wagtailadmin/notifications/approved.html:1
|
||||
#, python-format
|
||||
|
@ -533,16 +573,19 @@ msgid "You can edit the privacy settings on:"
|
|||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/page_privacy/set_privacy.html:6
|
||||
msgid "<b>Note:</b> privacy changes apply to all children of this page too."
|
||||
msgid "Privacy changes apply to all children of this page too."
|
||||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/pages/_moderator_userbar.html:4
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Previewing '%(title)s', submitted by %(submitted_by)s on %(submitted_on)s.\n"
|
||||
" Previewing '%(title)s', submitted by %(submitted_by)s on "
|
||||
"%(submitted_on)s.\n"
|
||||
" "
|
||||
msgstr "\nПреглед на '%(title)s', предоставена от %(submitted_by)s на %(submitted_on)s."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Преглед на '%(title)s', предоставена от %(submitted_by)s на %(submitted_on)s."
|
||||
|
||||
#: templates/wagtailadmin/pages/_privacy_indicator.html:9
|
||||
msgid "Privacy"
|
||||
|
@ -588,16 +631,26 @@ msgid ""
|
|||
" "
|
||||
msgid_plural ""
|
||||
"\n"
|
||||
" This will also delete %(descendant_count)s more subpages.\n"
|
||||
" This will also delete %(descendant_count)s more "
|
||||
"subpages.\n"
|
||||
" "
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
" Това ще изтрие още една подстраница.\n"
|
||||
" "
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
" Това ще изтрие още %(descendant_count)s подстраници.\n"
|
||||
" "
|
||||
msgstr[0] "\n Това ще изтрие още една подстраница.\n "
|
||||
msgstr[1] "\n Това ще изтрие още %(descendant_count)s подстраници.\n "
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_delete.html:22
|
||||
msgid ""
|
||||
"Alternatively you can unpublish the page. This removes the page from public "
|
||||
"view and you can edit or publish it again later."
|
||||
msgstr "Като алтернатива можете да прекратите публикуването на страницата. Това премахва страницата от обществен достъп и ще можете да редактирате или да го публикувате отново по-късно."
|
||||
msgstr ""
|
||||
"Като алтернатива можете да прекратите публикуването на страницата. Това "
|
||||
"премахва страницата от обществен достъп и ще можете да редактирате или да го "
|
||||
"публикувате отново по-късно."
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_delete.html:26
|
||||
msgid "Delete it"
|
||||
|
@ -628,7 +681,9 @@ msgstr "Сигурни ли сте, че желаете да преместит
|
|||
msgid ""
|
||||
"Are you sure you want to move this page and all of its children into "
|
||||
"'%(title)s'?"
|
||||
msgstr "Сигурни ли сте, че искате да преместите страницата и принадлежащите към нея дъщерни страници в '%(title)s'?"
|
||||
msgstr ""
|
||||
"Сигурни ли сте, че искате да преместите страницата и принадлежащите към нея "
|
||||
"дъщерни страници в '%(title)s'?"
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_move.html:18
|
||||
msgid "Yes, move this page"
|
||||
|
@ -855,7 +910,10 @@ msgid ""
|
|||
"\n"
|
||||
" Page %(page_number)s of %(num_pages)s.\n"
|
||||
" "
|
||||
msgstr "\n Страница %(page_number)s от %(num_pages)s.\n "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Страница %(page_number)s от %(num_pages)s.\n"
|
||||
" "
|
||||
|
||||
#: templates/wagtailadmin/pages/search_results.html:54
|
||||
#, python-format
|
||||
|
@ -994,66 +1052,66 @@ msgstr "Паролата ви бе променена успешно!"
|
|||
msgid "Your preferences have been updated successfully!"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:169 views/pages.py:286
|
||||
#: views/pages.py:167 views/pages.py:284
|
||||
msgid "Go live date/time must be before expiry date/time"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:179 views/pages.py:296
|
||||
#: views/pages.py:177 views/pages.py:294
|
||||
msgid "Expiry date/time must be in the future"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:219 views/pages.py:351 views/pages.py:791
|
||||
#: views/pages.py:217 views/pages.py:349 views/pages.py:766
|
||||
msgid "Page '{0}' published."
|
||||
msgstr "Страница '{0}' е публикувана."
|
||||
|
||||
#: views/pages.py:221 views/pages.py:353
|
||||
#: views/pages.py:219 views/pages.py:351
|
||||
msgid "Page '{0}' submitted for moderation."
|
||||
msgstr "Страница '{0}' е предоставена за модерация."
|
||||
|
||||
#: views/pages.py:224
|
||||
#: views/pages.py:222
|
||||
msgid "Page '{0}' created."
|
||||
msgstr "Страница '{0}' е създадена."
|
||||
|
||||
#: views/pages.py:233
|
||||
#: views/pages.py:231
|
||||
msgid "The page could not be created due to validation errors"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:356
|
||||
#: views/pages.py:354
|
||||
msgid "Page '{0}' updated."
|
||||
msgstr "Страница '{0}' обновена."
|
||||
|
||||
#: views/pages.py:365
|
||||
#: views/pages.py:363
|
||||
msgid "The page could not be saved due to validation errors"
|
||||
msgstr "Тази страница не можеше да бъде запазена поради валидационни грешки"
|
||||
|
||||
#: views/pages.py:378
|
||||
#: views/pages.py:376
|
||||
msgid "This page is currently awaiting moderation"
|
||||
msgstr "Тази страница очаква да бъде модерирана"
|
||||
|
||||
#: views/pages.py:409
|
||||
#: views/pages.py:407
|
||||
msgid "Page '{0}' deleted."
|
||||
msgstr "Страница '{0}' е изтрита."
|
||||
|
||||
#: views/pages.py:575
|
||||
#: views/pages.py:550
|
||||
msgid "Page '{0}' unpublished."
|
||||
msgstr "Страница '{0}' отменена от публикуване."
|
||||
|
||||
#: views/pages.py:627
|
||||
#: views/pages.py:602
|
||||
msgid "Page '{0}' moved."
|
||||
msgstr "Страница '{0}' преместена."
|
||||
|
||||
#: views/pages.py:709
|
||||
#: views/pages.py:684
|
||||
msgid "Page '{0}' and {1} subpages copied."
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:711
|
||||
#: views/pages.py:686
|
||||
msgid "Page '{0}' copied."
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:785 views/pages.py:804 views/pages.py:824
|
||||
#: views/pages.py:760 views/pages.py:779 views/pages.py:799
|
||||
msgid "The page '{0}' is not currently awaiting moderation."
|
||||
msgstr "Страница '{0}' не очаква да бъде модерирана."
|
||||
|
||||
#: views/pages.py:810
|
||||
#: views/pages.py:785
|
||||
msgid "Page '{0}' rejected for publication."
|
||||
msgstr "Страница '{0}' отхвърлена от публикуване."
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -1,28 +1,29 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# David Llop <d.lloople@gmail.com>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Wagtail\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-08-01 16:38+0100\n"
|
||||
"POT-Creation-Date: 2014-09-11 16:37+0100\n"
|
||||
"PO-Revision-Date: 2014-08-01 15:43+0000\n"
|
||||
"Last-Translator: Karl Hobley <karl@torchbox.com>\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/wagtail/language/ca/)\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/wagtail/language/"
|
||||
"ca/)\n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ca\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: edit_handlers.py:627
|
||||
#: edit_handlers.py:631
|
||||
msgid "Scheduled publishing"
|
||||
msgstr ""
|
||||
|
||||
#: edit_handlers.py:641
|
||||
#: edit_handlers.py:645
|
||||
msgid "Common page configuration"
|
||||
msgstr "Configuració de la pàgina comú"
|
||||
|
||||
|
@ -50,7 +51,9 @@ msgstr "Si us plau escriu el teu correu"
|
|||
msgid ""
|
||||
"Sorry, you cannot reset your password here as your user account is managed "
|
||||
"by another server."
|
||||
msgstr "Ho sentim, no pots reiniciar la teva contrasenya aquí ja que la teva conta d'usuari es administrada per un altre servidor"
|
||||
msgstr ""
|
||||
"Ho sentim, no pots reiniciar la teva contrasenya aquí ja que la teva conta "
|
||||
"d'usuari es administrada per un altre servidor"
|
||||
|
||||
#: forms.py:76
|
||||
msgid "This email address is not recognised."
|
||||
|
@ -98,7 +101,7 @@ msgid_plural ""
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: forms.py:124 views/pages.py:155 views/pages.py:272
|
||||
#: forms.py:124 views/pages.py:153 views/pages.py:270
|
||||
msgid "This slug is already in use"
|
||||
msgstr "Aquest llimac ja està en ús"
|
||||
|
||||
|
@ -115,6 +118,16 @@ msgstr ""
|
|||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: wagtail_hooks.py:15 templates/wagtailadmin/chooser/_search_results.html:12
|
||||
msgid "Explorer"
|
||||
msgstr "Explorador"
|
||||
|
||||
#: wagtail_hooks.py:23 templates/wagtailadmin/chooser/_search_form.html:7
|
||||
#: templates/wagtailadmin/pages/search.html:3
|
||||
#: templates/wagtailadmin/pages/search.html:16
|
||||
msgid "Search"
|
||||
msgstr "Cercar"
|
||||
|
||||
#: templates/wagtailadmin/base.html:7 templates/wagtailadmin/home.html:4
|
||||
msgid "Dashboard"
|
||||
msgstr "Tauler de control"
|
||||
|
@ -132,7 +145,9 @@ msgstr "Benvingut al Wagtail CMS del lloc %(site_name)s"
|
|||
msgid ""
|
||||
"This is your dashboard on which helpful information about content you've "
|
||||
"created will be displayed."
|
||||
msgstr "Aquest es el teu tauler de control on es mostrarà informació útil sobre el contingut que has creat"
|
||||
msgstr ""
|
||||
"Aquest es el teu tauler de control on es mostrarà informació útil sobre el "
|
||||
"contingut que has creat"
|
||||
|
||||
#: templates/wagtailadmin/login.html:4 templates/wagtailadmin/login.html:59
|
||||
msgid "Sign in"
|
||||
|
@ -140,7 +155,9 @@ msgstr "Registra't"
|
|||
|
||||
#: templates/wagtailadmin/login.html:18
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "El teu nom d'usuari i la teva contrasenya no coincideixen. Si us plau torna-ho a intentar"
|
||||
msgstr ""
|
||||
"El teu nom d'usuari i la teva contrasenya no coincideixen. Si us plau torna-"
|
||||
"ho a intentar"
|
||||
|
||||
#: templates/wagtailadmin/login.html:26
|
||||
msgid "Sign in to Wagtail"
|
||||
|
@ -164,7 +181,10 @@ msgid ""
|
|||
"Your avatar image is provided by Gravatar and is connected to your email "
|
||||
"address. With a Gravatar account you can set an avatar for any number of "
|
||||
"other email addresses you use."
|
||||
msgstr "La teva imatge de perfil és subministrada per Gravatar i està conectada al teu correu. Amb una conta de Gravatar pots definir una imatge de perfil per cadascuna de la resta d'adreces de correu que fas servir."
|
||||
msgstr ""
|
||||
"La teva imatge de perfil és subministrada per Gravatar i està conectada al "
|
||||
"teu correu. Amb una conta de Gravatar pots definir una imatge de perfil per "
|
||||
"cadascuna de la resta d'adreces de correu que fas servir."
|
||||
|
||||
#: templates/wagtailadmin/account/account.html:25
|
||||
#: templates/wagtailadmin/account/change_password.html:4
|
||||
|
@ -191,7 +211,9 @@ msgstr "Canvia la contrasenya"
|
|||
#: templates/wagtailadmin/account/change_password.html:21
|
||||
msgid ""
|
||||
"Your password can't be changed here. Please contact a site administrator."
|
||||
msgstr "La teva contrasenya no es pot canviar des d'aquí. Si us plau contacta amb l'administrador de la web"
|
||||
msgstr ""
|
||||
"La teva contrasenya no es pot canviar des d'aquí. Si us plau contacta amb "
|
||||
"l'administrador de la web"
|
||||
|
||||
#: templates/wagtailadmin/account/notification_preferences.html:4
|
||||
#: templates/wagtailadmin/account/notification_preferences.html:6
|
||||
|
@ -262,19 +284,16 @@ msgstr "Enllaç extern"
|
|||
msgid "Email link"
|
||||
msgstr "Enllaç de correu electrònic"
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_form.html:7
|
||||
#: templates/wagtailadmin/pages/search.html:3
|
||||
#: templates/wagtailadmin/pages/search.html:16
|
||||
#: templatetags/wagtailadmin_tags.py:36
|
||||
msgid "Search"
|
||||
msgstr "Cercar"
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:5
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Only pages of type \"%(type)s\" may be chosen for this field. "
|
||||
"Search results will exclude pages of other types.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:3
|
||||
#: templatetags/wagtailadmin_tags.py:35
|
||||
msgid "Explorer"
|
||||
msgstr "Explorador"
|
||||
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:8
|
||||
#: templates/wagtailadmin/chooser/_search_results.html:16
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
@ -284,10 +303,19 @@ msgid_plural ""
|
|||
"\n"
|
||||
" There are %(counter)s matches\n"
|
||||
" "
|
||||
msgstr[0] "\nHi ha un resultat"
|
||||
msgstr[1] "\nHi han %(counter)s resultats"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"Hi ha un resultat"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"Hi han %(counter)s resultats"
|
||||
|
||||
#: templates/wagtailadmin/chooser/browse.html:2
|
||||
#: templates/wagtailadmin/chooser/browse.html:3
|
||||
#, fuzzy
|
||||
msgid "Choose"
|
||||
msgstr "Escull una pàgina"
|
||||
|
||||
#: templates/wagtailadmin/chooser/browse.html:6
|
||||
#: templates/wagtailadmin/chooser/search.html:2
|
||||
#: templates/wagtailadmin/edit_handlers/page_chooser_panel.html:13
|
||||
msgid "Choose a page"
|
||||
|
@ -442,8 +470,12 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_pages)s</span> Pages\n"
|
||||
" "
|
||||
msgstr[0] "\n<span>%(total_pages)s</span> Pàgina"
|
||||
msgstr[1] "\n<span>%(total_pages)s</span>Pàgines"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"<span>%(total_pages)s</span> Pàgina"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"<span>%(total_pages)s</span>Pàgines"
|
||||
|
||||
#: templates/wagtailadmin/home/site_summary.html:16
|
||||
#, python-format
|
||||
|
@ -455,8 +487,12 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_images)s</span> Images\n"
|
||||
" "
|
||||
msgstr[0] "\n<span>%(total_images)s</span> Imatge"
|
||||
msgstr[1] "\n<span>%(total_images)s</span> Imatges"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"<span>%(total_images)s</span> Imatge"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"<span>%(total_images)s</span> Imatges"
|
||||
|
||||
#: templates/wagtailadmin/home/site_summary.html:25
|
||||
#, python-format
|
||||
|
@ -468,8 +504,12 @@ msgid_plural ""
|
|||
"\n"
|
||||
" <span>%(total_docs)s</span> Documents\n"
|
||||
" "
|
||||
msgstr[0] "\n<span>%(total_docs)s</span> Document"
|
||||
msgstr[1] "\n<span>%(total_docs)s</span> Documents"
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"<span>%(total_docs)s</span> Document"
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"<span>%(total_docs)s</span> Documents"
|
||||
|
||||
#: templates/wagtailadmin/notifications/approved.html:1
|
||||
#, python-format
|
||||
|
@ -532,16 +572,19 @@ msgid "You can edit the privacy settings on:"
|
|||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/page_privacy/set_privacy.html:6
|
||||
msgid "<b>Note:</b> privacy changes apply to all children of this page too."
|
||||
msgid "Privacy changes apply to all children of this page too."
|
||||
msgstr ""
|
||||
|
||||
#: templates/wagtailadmin/pages/_moderator_userbar.html:4
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Previewing '%(title)s', submitted by %(submitted_by)s on %(submitted_on)s.\n"
|
||||
" Previewing '%(title)s', submitted by %(submitted_by)s on "
|
||||
"%(submitted_on)s.\n"
|
||||
" "
|
||||
msgstr "\nPrevisualitzant '%(title)s, enviada per %(submitted_by)s el %(submitted_on)s."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Previsualitzant '%(title)s, enviada per %(submitted_by)s el %(submitted_on)s."
|
||||
|
||||
#: templates/wagtailadmin/pages/_privacy_indicator.html:9
|
||||
msgid "Privacy"
|
||||
|
@ -587,16 +630,23 @@ msgid ""
|
|||
" "
|
||||
msgid_plural ""
|
||||
"\n"
|
||||
" This will also delete %(descendant_count)s more subpages.\n"
|
||||
" This will also delete %(descendant_count)s more "
|
||||
"subpages.\n"
|
||||
" "
|
||||
msgstr[0] "\nAixò també esborrarà una subpàgina més."
|
||||
msgstr[1] "\nAixò també esborrarà %(descendant_count)s subpàgines més."
|
||||
msgstr[0] ""
|
||||
"\n"
|
||||
"Això també esborrarà una subpàgina més."
|
||||
msgstr[1] ""
|
||||
"\n"
|
||||
"Això també esborrarà %(descendant_count)s subpàgines més."
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_delete.html:22
|
||||
msgid ""
|
||||
"Alternatively you can unpublish the page. This removes the page from public "
|
||||
"view and you can edit or publish it again later."
|
||||
msgstr "Alternativament pots despublicar la pàgina. Això treu la pàgina de la vista pública i podràs editar-la o tornar-la a publicar desprès."
|
||||
msgstr ""
|
||||
"Alternativament pots despublicar la pàgina. Això treu la pàgina de la vista "
|
||||
"pública i podràs editar-la o tornar-la a publicar desprès."
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_delete.html:26
|
||||
msgid "Delete it"
|
||||
|
@ -627,7 +677,9 @@ msgstr "Estàs segur que vols moure aquesta pàgina dins de '%(title)s'?"
|
|||
msgid ""
|
||||
"Are you sure you want to move this page and all of its children into "
|
||||
"'%(title)s'?"
|
||||
msgstr "Estàs segur que vols moure aquesta pàgina i els seus fills dins de '%(title)s'?"
|
||||
msgstr ""
|
||||
"Estàs segur que vols moure aquesta pàgina i els seus fills dins de "
|
||||
"'%(title)s'?"
|
||||
|
||||
#: templates/wagtailadmin/pages/confirm_move.html:18
|
||||
msgid "Yes, move this page"
|
||||
|
@ -854,7 +906,9 @@ msgid ""
|
|||
"\n"
|
||||
" Page %(page_number)s of %(num_pages)s.\n"
|
||||
" "
|
||||
msgstr "\nPàgina %(page_number)s de %(num_pages)s."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Pàgina %(page_number)s de %(num_pages)s."
|
||||
|
||||
#: templates/wagtailadmin/pages/search_results.html:54
|
||||
#, python-format
|
||||
|
@ -993,66 +1047,66 @@ msgstr "S'ha canviat la teva contrasenya!"
|
|||
msgid "Your preferences have been updated successfully!"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:169 views/pages.py:286
|
||||
#: views/pages.py:167 views/pages.py:284
|
||||
msgid "Go live date/time must be before expiry date/time"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:179 views/pages.py:296
|
||||
#: views/pages.py:177 views/pages.py:294
|
||||
msgid "Expiry date/time must be in the future"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:219 views/pages.py:351 views/pages.py:791
|
||||
#: views/pages.py:217 views/pages.py:349 views/pages.py:766
|
||||
msgid "Page '{0}' published."
|
||||
msgstr "Pàgina '{0}' publicada."
|
||||
|
||||
#: views/pages.py:221 views/pages.py:353
|
||||
#: views/pages.py:219 views/pages.py:351
|
||||
msgid "Page '{0}' submitted for moderation."
|
||||
msgstr "Pàgina '{0}' enviada per revisió"
|
||||
|
||||
#: views/pages.py:224
|
||||
#: views/pages.py:222
|
||||
msgid "Page '{0}' created."
|
||||
msgstr "Pàgina '{0}' creada."
|
||||
|
||||
#: views/pages.py:233
|
||||
#: views/pages.py:231
|
||||
msgid "The page could not be created due to validation errors"
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:356
|
||||
#: views/pages.py:354
|
||||
msgid "Page '{0}' updated."
|
||||
msgstr "Pàgina '{0}' actualitzada."
|
||||
|
||||
#: views/pages.py:365
|
||||
#: views/pages.py:363
|
||||
msgid "The page could not be saved due to validation errors"
|
||||
msgstr "La pàgina no s'ha pogut guardar degut a errors de validació"
|
||||
|
||||
#: views/pages.py:378
|
||||
#: views/pages.py:376
|
||||
msgid "This page is currently awaiting moderation"
|
||||
msgstr "Aquesta pàgina està esperant moderació"
|
||||
|
||||
#: views/pages.py:409
|
||||
#: views/pages.py:407
|
||||
msgid "Page '{0}' deleted."
|
||||
msgstr "Pàgina '{0}' eliminada."
|
||||
|
||||
#: views/pages.py:575
|
||||
#: views/pages.py:550
|
||||
msgid "Page '{0}' unpublished."
|
||||
msgstr "Pàgina '{0}' despublicada."
|
||||
|
||||
#: views/pages.py:627
|
||||
#: views/pages.py:602
|
||||
msgid "Page '{0}' moved."
|
||||
msgstr "Pàgina '{0}' moguda."
|
||||
|
||||
#: views/pages.py:709
|
||||
#: views/pages.py:684
|
||||
msgid "Page '{0}' and {1} subpages copied."
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:711
|
||||
#: views/pages.py:686
|
||||
msgid "Page '{0}' copied."
|
||||
msgstr ""
|
||||
|
||||
#: views/pages.py:785 views/pages.py:804 views/pages.py:824
|
||||
#: views/pages.py:760 views/pages.py:779 views/pages.py:799
|
||||
msgid "The page '{0}' is not currently awaiting moderation."
|
||||
msgstr "La pàgina '{0}' ja no es troba esperant moderació."
|
||||
|
||||
#: views/pages.py:810
|
||||
#: views/pages.py:785
|
||||
msgid "Page '{0}' rejected for publication."
|
||||
msgstr "La pàgina '{0}' ha estat rebutjada per publicació"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue