Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Dave Cranwell 2015-04-01 10:24:29 +01:00
commit bb0039b29a
98 changed files with 3055 additions and 865 deletions

View file

@ -39,6 +39,8 @@ Changelog
* Date / time pickers now consistently use times without seconds, to prevent Javascript behaviour glitches when focusing / unfocusing fields
* Added hooks `register_rich_text_embed_handler` and `register_rich_text_link_handler` for customising link / embed handling within rich text fields
* Added hook `construct_homepage_summary_items` for customising the site summary panel on the admin homepage
* No longer automatically tries to use Celery for sending notification emails
* Added "Add child page" button to admin userbar (Eric Drechsel)
0.8.6 (10.03.2015)

View file

@ -28,21 +28,6 @@ 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``.
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
------

View file

@ -285,10 +285,10 @@ Any block type is valid as the sub-block type, including structural types:
.. code-block:: python
('ingredients_list', blocks.ListBlock(blocks.StructBlock(
('ingredients_list', blocks.ListBlock(blocks.StructBlock([
('ingredient', blocks.CharBlock(required=True)),
('amount', blocks.CharBlock()),
)))
])))
StreamBlock
@ -305,9 +305,9 @@ A block consisting of a sequence of sub-blocks of different types, which can be
('image', ImageChooserBlock()),
('quotation', blocks.StructBlock([
('text', blocks.TextBlock()),
('author', blocks.CharBlock),
('author', blocks.CharBlock()),
])),
('video', blocks.EmbedBlock()),
('video', EmbedBlock()),
],
icon='cogs'
))
@ -321,9 +321,9 @@ As with StructBlock, the list of sub-blocks can also be provided as a subclass o
image = ImageChooserBlock()
quotation = blocks.StructBlock([
('text', blocks.TextBlock()),
('author', blocks.CharBlock),
('author', blocks.CharBlock()),
])
video = blocks.EmbedBlock
video = EmbedBlock()
class Meta:
icon='cogs'

View file

@ -51,6 +51,7 @@ Admin
* Added pagination to the snippets listing and chooser
* Page / document / image / snippet choosers now include a link to edit the chosen item
* Plain text fields in the page editor now use auto-expanding text areas
* Added "Add child page" button to admin userbar
**Page editor**
@ -85,6 +86,7 @@ Project template
* The Vagrantfile now listens on port 8000
* Removed ``LOGIN_URL`` and ``LOGIN_REDIRECT_URL`` settings (as Wagtail no longer requires these)
* Removed example Celery configuration from ``production.py`` and ``requirements.txt``
Search
@ -123,6 +125,17 @@ It is no longer necessary to pass the base model as a parameter, so this declara
The old format is now deprecated; all existing ``InlinePanel`` declarations should be updated to the new format.
Celery no longer automatically used for sending notification emails
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Previously, Wagtail would try to use Celery whenever the ``djcelery`` module was
installed, even if Celery wasn't actually set up. This could cause a very hard
to track down problem where notification emails would not be sent so this
functionality has now been removed.
If you would like to keep using Celery for sending notification emails, have a
look at: `django-celery-email <https://pypi.python.org/pypi/django-celery-email>`_
You no longer need ``LOGIN_URL`` and ``LOGIN_REDIRECT_URL`` to point to Wagtail admin.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -1,4 +1,4 @@
from django.db import models
from django.apps import apps
from wagtail.wagtailcore.signals import page_published, page_unpublished
@ -15,8 +15,8 @@ def page_unpublished_signal_handler(instance, **kwargs):
def register_signal_handlers():
# Get list of models that are page types
Page = models.get_model('wagtailcore', 'Page')
indexed_models = [model for model in models.get_models() if issubclass(model, Page)]
Page = apps.get_model('wagtailcore', 'Page')
indexed_models = [model for model in apps.get_models() if issubclass(model, Page)]
# Loop through list and register signal handlers for each one
for model in indexed_models:

View file

@ -1,7 +1,7 @@
from django.test import TestCase, RequestFactory
from wagtail.wagtailcore.models import Page, Site
from wagtail.tests.models import RoutablePageTest, routable_page_external_view
from wagtail.tests.routablepage.models import RoutablePageTest, routable_page_external_view
from wagtail.contrib.wagtailroutablepage.templatetags.wagtailroutablepage_tags import routablepageurl

View file

@ -2,7 +2,7 @@ from django.test import TestCase
from django.core.cache import cache
from wagtail.wagtailcore.models import Page, PageViewRestriction, Site
from wagtail.tests.models import SimplePage, EventIndex
from wagtail.tests.testapp.models import SimplePage, EventIndex
from .sitemap_generator import Sitemap

View file

@ -13,19 +13,6 @@ TEMPLATE_DEBUG = False
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

View file

@ -8,4 +8,3 @@ wagtail==1.0b1
# Recommended components to improve performance in production:
# django-redis==3.8.2
# django-celery==3.1.10

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('customuser', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='groups',
field=models.ManyToManyField(to='auth.Group', verbose_name='groups', help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.', related_name='user_set', blank=True, related_query_name='user'),
preserve_default=True,
),
migrations.AlterField(
model_name='customuser',
name='user_permissions',
field=models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', help_text='Specific permissions for this user.', related_name='user_set', blank=True, related_query_name='user'),
preserve_default=True,
),
]

View file

@ -0,0 +1,47 @@
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class CustomUserManager(BaseUserManager):
def _create_user(self, username, email, password,
is_staff, is_superuser, **extra_fields):
"""
Creates and saves a User with the given username, email and password.
"""
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, False, False,
**extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
return self._create_user(username, email, password, True, True,
**extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=100, unique=True)
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)
USERNAME_FIELD = 'username'
objects = CustomUserManager()
def get_full_name(self):
return self.first_name + ' ' + self.last_name
def get_short_name(self):
return self.first_name

View file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,513 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
import modelcluster.tags
import wagtail.wagtailcore.fields
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
('wagtailimages', '0005_make_filter_spec_unique'),
('taggit', '0001_initial'),
('wagtaildocs', '0002_initial_data'),
('wagtailcore', '0013_update_golive_expire_help_text'),
]
operations = [
migrations.CreateModel(
name='BlogEntryPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('body', wagtail.wagtailcore.fields.RichTextField()),
('date', models.DateField(verbose_name='Post date')),
('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='BlogEntryPageCarouselItem',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='BlogEntryPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='BlogEntryPageTag',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('content_object', modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='tagged_items')),
('tag', models.ForeignKey(to='taggit.Tag', related_name='demosite_blogentrypagetag_items')),
],
options={
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='BlogIndexPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='BlogIndexPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='ContactPage',
fields=[
('telephone', models.CharField(blank=True, max_length=20)),
('email', models.EmailField(blank=True, max_length=75)),
('address_1', models.CharField(blank=True, max_length=255)),
('address_2', models.CharField(blank=True, max_length=255)),
('city', models.CharField(blank=True, max_length=255)),
('country', models.CharField(blank=True, max_length=255)),
('post_code', models.CharField(blank=True, max_length=10)),
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('body', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page', models.Model),
),
migrations.CreateModel(
name='EventIndexPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='EventIndexPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='EventPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('date_from', models.DateField(verbose_name='Start date')),
('date_to', models.DateField(help_text='Not required if event is on a single day', null=True, verbose_name='End date', blank=True)),
('time_from', models.TimeField(null=True, verbose_name='Start time', blank=True)),
('time_to', models.TimeField(null=True, verbose_name='End time', blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='EventPageCarouselItem',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='EventPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='EventPageSpeaker',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='HomePage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('body', wagtail.wagtailcore.fields.RichTextField(blank=True)),
],
options={
'verbose_name': 'Homepage',
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='HomePageCarouselItem',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='HomePageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='PersonPage',
fields=[
('telephone', models.CharField(blank=True, max_length=20)),
('email', models.EmailField(blank=True, max_length=75)),
('address_1', models.CharField(blank=True, max_length=255)),
('address_2', models.CharField(blank=True, max_length=255)),
('city', models.CharField(blank=True, max_length=255)),
('country', models.CharField(blank=True, max_length=255)),
('post_code', models.CharField(blank=True, max_length=10)),
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('first_name', models.CharField(max_length=255)),
('last_name', models.CharField(max_length=255)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('biography', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page', models.Model),
),
migrations.CreateModel(
name='PersonPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='StandardIndexPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='StandardIndexPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='StandardPage',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, parent_link=True, related_name='+', primary_key=True)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('body', wagtail.wagtailcore.fields.RichTextField(blank=True)),
('feed_image', models.ForeignKey(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='StandardPageCarouselItem',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('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(to='wagtailimages.Image', blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', null=True)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
('link_page', models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True)),
('page', modelcluster.fields.ParentalKey(to='demosite.StandardPage', related_name='carousel_items')),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='StandardPageRelatedLink',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('sort_order', models.IntegerField(null=True, editable=False, blank=True)),
('link_external', models.URLField(blank=True, verbose_name='External link')),
('title', models.CharField(help_text='Link title', max_length=255)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', blank=True, related_name='+', null=True)),
('link_page', models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True)),
('page', modelcluster.fields.ParentalKey(to='demosite.StandardPage', related_name='related_links')),
],
options={
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.AddField(
model_name='standardindexpagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='standardindexpagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.StandardIndexPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='personpagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='personpagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.PersonPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='homepagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='homepagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.HomePage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='homepagecarouselitem',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='homepagecarouselitem',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.HomePage', related_name='carousel_items'),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagespeaker',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagespeaker',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='speakers'),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagecarouselitem',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='eventpagecarouselitem',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.EventPage', related_name='carousel_items'),
preserve_default=True,
),
migrations.AddField(
model_name='eventindexpagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='eventindexpagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.EventIndexPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='blogindexpagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='blogindexpagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.BlogIndexPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='blogentrypagerelatedlink',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='blogentrypagerelatedlink',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='related_links'),
preserve_default=True,
),
migrations.AddField(
model_name='blogentrypagecarouselitem',
name='link_page',
field=models.ForeignKey(to='wagtailcore.Page', blank=True, related_name='+', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='blogentrypagecarouselitem',
name='page',
field=modelcluster.fields.ParentalKey(to='demosite.BlogEntryPage', related_name='carousel_items'),
preserve_default=True,
),
migrations.AddField(
model_name='blogentrypage',
name='tags',
field=modelcluster.tags.ClusterTaggableManager(help_text='A comma-separated list of tags.', through='demosite.BlogEntryPageTag', blank=True, verbose_name='Tags', to='taggit.Tag'),
preserve_default=True,
),
]

View file

@ -0,0 +1,594 @@
from django.db import models
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from modelcluster.fields import ParentalKey
from modelcluster.tags import ClusterTaggableManager
from taggit.models import Tag, TaggedItemBase
from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, \
InlinePanel, PageChooserPanel
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel
from wagtail.wagtailsnippets.models import register_snippet
from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
from wagtail.wagtailsearch import index
# ABSTRACT MODELS
# =============================
class AbstractLinkFields(models.Model):
link_external = models.URLField("External link", blank=True)
link_page = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
related_name='+'
)
link_document = models.ForeignKey(
'wagtaildocs.Document',
null=True,
blank=True,
related_name='+'
)
@property
def link(self):
if self.link_page:
return self.link_page.url
elif self.link_document:
return self.link_document.url
else:
return self.link_external
api_fields = ('link', )
panels = [
FieldPanel('link_external'),
PageChooserPanel('link_page'),
DocumentChooserPanel('link_document'),
]
class Meta:
abstract = True
class AbstractRelatedLink(AbstractLinkFields):
title = models.CharField(max_length=255, help_text="Link title")
api_fields = ('title', ) + AbstractLinkFields.api_fields
panels = [
FieldPanel('title'),
MultiFieldPanel(AbstractLinkFields.panels, "Link"),
]
class Meta:
abstract = True
class AbstractCarouselItem(AbstractLinkFields):
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
embed_url = models.URLField("Embed URL", blank=True)
caption = models.CharField(max_length=255, blank=True)
api_fields = (
'image',
'embed_url',
'caption',
) + AbstractLinkFields.api_fields
panels = [
ImageChooserPanel('image'),
FieldPanel('embed_url'),
FieldPanel('caption'),
MultiFieldPanel(AbstractLinkFields.panels, "Link"),
]
class Meta:
abstract = True
class ContactFieldsMixin(models.Model):
telephone = models.CharField(max_length=20, blank=True)
email = models.EmailField(blank=True)
address_1 = models.CharField(max_length=255, blank=True)
address_2 = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=255, blank=True)
country = models.CharField(max_length=255, blank=True)
post_code = models.CharField(max_length=10, blank=True)
api_fields = (
'telephone',
'email',
'address_1',
'address_2',
'city',
'country',
'post_code',
)
panels = [
FieldPanel('telephone'),
FieldPanel('email'),
FieldPanel('address_1'),
FieldPanel('address_2'),
FieldPanel('city'),
FieldPanel('country'),
FieldPanel('post_code'),
]
class Meta:
abstract = True
# PAGE MODELS
# =============================
# Home page
class HomePage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
body = RichTextField(blank=True)
api_fields = (
'body',
'carousel_items',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('body'),
)
class Meta:
verbose_name = "Homepage"
class HomePageCarouselItem(Orderable, AbstractCarouselItem):
page = ParentalKey('HomePage', related_name='carousel_items')
class HomePageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('HomePage', related_name='related_links')
HomePage.content_panels = Page.content_panels + [
FieldPanel('body', classname="full"),
InlinePanel(HomePage, 'carousel_items', label="Carousel items"),
InlinePanel(HomePage, 'related_links', label="Related links"),
]
# Standard pages
class StandardPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
intro = RichTextField(blank=True)
body = RichTextField(blank=True)
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'intro',
'body',
'feed_image',
'carousel_items',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('intro'),
index.SearchField('body'),
)
class StandardPageCarouselItem(Orderable, AbstractCarouselItem):
page = ParentalKey('StandardPage', related_name='carousel_items')
class StandardPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('StandardPage', related_name='related_links')
StandardPage.content_panels = Page.content_panels + [
FieldPanel('intro', classname="full"),
InlinePanel(StandardPage, 'carousel_items', label="Carousel items"),
FieldPanel('body', classname="full"),
InlinePanel(StandardPage, 'related_links', label="Related links"),
]
StandardPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
]
class StandardIndexPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
intro = RichTextField(blank=True)
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'intro',
'feed_image',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('intro'),
)
class StandardIndexPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('StandardIndexPage', related_name='related_links')
StandardIndexPage.content_panels = Page.content_panels + [
FieldPanel('intro', classname="full"),
InlinePanel(StandardIndexPage, 'related_links', label="Related links"),
]
StandardIndexPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
]
# Blog pages
class BlogEntryPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
body = RichTextField()
tags = ClusterTaggableManager(through='BlogEntryPageTag', blank=True)
date = models.DateField("Post date")
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'body',
'tags',
'date',
'feed_image',
'carousel_items',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('body'),
)
def get_blog_index(self):
# Find closest ancestor which is a blog index
return BlogIndexPage.ancestor_of(self).last()
class BlogEntryPageCarouselItem(Orderable, AbstractCarouselItem):
page = ParentalKey('BlogEntryPage', related_name='carousel_items')
class BlogEntryPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('BlogEntryPage', related_name='related_links')
class BlogEntryPageTag(TaggedItemBase):
content_object = ParentalKey('BlogEntryPage', related_name='tagged_items')
BlogEntryPage.content_panels = Page.content_panels + [
FieldPanel('date'),
FieldPanel('body', classname="full"),
InlinePanel(BlogEntryPage, 'carousel_items', label="Carousel items"),
InlinePanel(BlogEntryPage, 'related_links', label="Related links"),
]
BlogEntryPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
FieldPanel('tags'),
]
class BlogIndexPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
intro = RichTextField(blank=True)
api_fields = (
'intro',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('intro'),
)
def get_blog_entries(self):
# Get list of live blog pages that are descendants of this page
entries = BlogEntryPage.objects.descendant_of(self).live()
# Order by most recent date first
entries = entries.order_by('-date')
return entries
def get_context(self, request):
# Get blog entries
entries = self.get_blog_entries()
# Filter by tag
tag = request.GET.get('tag')
if tag:
entries = entries.filter(tags__name=tag)
# Pagination
page = request.GET.get('page')
paginator = Paginator(entries, 10) # Show 10 entries per page
try:
entries = paginator.page(page)
except PageNotAnInteger:
entries = paginator.page(1)
except EmptyPage:
entries = paginator.page(paginator.num_pages)
# Update template context
context = super(BlogIndexPage, self).get_context(request)
context['entries'] = entries
return context
class BlogIndexPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('BlogIndexPage', related_name='related_links')
BlogIndexPage.content_panels = Page.content_panels + [
FieldPanel('intro', classname="full"),
InlinePanel(BlogIndexPage, 'related_links', label="Related links"),
]
# Events pages
class EventPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
AUDIENCE_CHOICES = (
('public', "Public"),
('private', "Private"),
)
date_from = models.DateField("Start date")
date_to = models.DateField(
"End date",
null=True,
blank=True,
help_text="Not required if event is on a single day"
)
time_from = models.TimeField("Start time", null=True, blank=True)
time_to = models.TimeField("End time", null=True, blank=True)
audience = models.CharField(max_length=255, choices=AUDIENCE_CHOICES)
location = models.CharField(max_length=255)
body = RichTextField(blank=True)
cost = models.CharField(max_length=255)
signup_link = models.URLField(blank=True)
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'date_from',
'date_to',
'time_from',
'time_to',
'audience',
'location',
'body',
'cost',
'signup_link',
'feed_image',
'carousel_items',
'related_links',
'speakers',
)
search_fields = Page.search_fields + (
index.SearchField('get_audience_display'),
index.SearchField('location'),
index.SearchField('body'),
)
def get_event_index(self):
# Find closest ancestor which is an event index
return EventIndexPage.objects.ancester_of(self).last()
class EventPageCarouselItem(Orderable, AbstractCarouselItem):
page = ParentalKey('EventPage', related_name='carousel_items')
class EventPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('EventPage', related_name='related_links')
class EventPageSpeaker(Orderable, AbstractLinkFields):
page = ParentalKey('EventPage', related_name='speakers')
first_name = models.CharField("Name", max_length=255, blank=True)
last_name = models.CharField("Surname", max_length=255, blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'first_name',
'last_name',
'image',
)
panels = [
FieldPanel('first_name'),
FieldPanel('last_name'),
ImageChooserPanel('image'),
MultiFieldPanel(AbstractLinkFields.panels, "Link"),
]
EventPage.content_panels = Page.content_panels + [
FieldPanel('date_from'),
FieldPanel('date_to'),
FieldPanel('time_from'),
FieldPanel('time_to'),
FieldPanel('location'),
FieldPanel('audience'),
FieldPanel('cost'),
FieldPanel('signup_link'),
InlinePanel(EventPage, 'carousel_items', label="Carousel items"),
FieldPanel('body', classname="full"),
InlinePanel(EventPage, 'speakers', label="Speakers"),
InlinePanel(EventPage, 'related_links', label="Related links"),
]
EventPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
]
class EventIndexPage(Page):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
intro = RichTextField(blank=True)
api_fields = (
'intro',
'related_links',
)
search_fields = Page.search_fields + (
index.SearchField('intro'),
)
def get_events(self):
# Get list of live event pages that are descendants of this page
events = EventPage.objects.descendant_of(self).live()
# Filter events list to get ones that are either
# running now or start in the future
events = events.filter(date_from__gte=date.today())
# Order by date
events = events.order_by('date_from')
return events
class EventIndexPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('EventIndexPage', related_name='related_links')
EventIndexPage.content_panels = Page.content_panels + [
FieldPanel('intro', classname="full"),
InlinePanel(EventIndexPage, 'related_links', label="Related links"),
]
# Person page
class PersonPage(Page, ContactFieldsMixin):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
intro = RichTextField(blank=True)
biography = RichTextField(blank=True)
image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'first_name',
'last_name',
'intro',
'biography',
'image',
'feed_image',
'related_links',
) + ContactFieldsMixin.api_fields
search_fields = Page.search_fields + (
index.SearchField('first_name'),
index.SearchField('last_name'),
index.SearchField('intro'),
index.SearchField('biography'),
)
class PersonPageRelatedLink(Orderable, AbstractRelatedLink):
page = ParentalKey('PersonPage', related_name='related_links')
PersonPage.content_panels = Page.content_panels + [
FieldPanel('first_name'),
FieldPanel('last_name'),
FieldPanel('intro', classname="full"),
FieldPanel('biography', classname="full"),
ImageChooserPanel('image'),
MultiFieldPanel(ContactFieldsMixin.panels, "Contact"),
InlinePanel(PersonPage, 'related_links', label="Related links"),
]
PersonPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
]
# Contact page
class ContactPage(Page, ContactFieldsMixin):
page_ptr = models.OneToOneField(Page, parent_link=True, related_name='+')
body = RichTextField(blank=True)
feed_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
api_fields = (
'body',
'feed_image',
) + ContactFieldsMixin.api_fields
search_fields = Page.search_fields + (
index.SearchField('body'),
)
ContactPage.content_panels = Page.content_panels + [
FieldPanel('body', classname="full"),
MultiFieldPanel(ContactFieldsMixin.panels, "Contact"),
]
ContactPage.promote_panels = [
MultiFieldPanel(Page.promote_panels, "Common page configuration"),
ImageChooserPanel('feed_image'),
]

View file

@ -1,20 +0,0 @@
# -*- 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,
),
]

View file

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0003_auto_20140905_0634'),
]
operations = [
migrations.DeleteModel(
name='SearchTestOldConfig',
),
migrations.DeleteModel(
name='SearchTestOldConfigList',
),
]

View file

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0002_initial_data'),
('tests', '0004_auto_20141008_0420'),
]
operations = [
migrations.CreateModel(
name='PageChooserModel',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('page', models.ForeignKey(help_text=b'help text', to='wagtailcore.Page')),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='SnippetChooserModel',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('advert', models.ForeignKey(help_text=b'help text', to='tests.Advert')),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0002_initial_data'),
('tests', '0004_auto_20141008_0420'),
]
operations = [
migrations.AlterField(
model_name='formfield',
name='choices',
field=models.CharField(help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='formfield',
name='default_value',
field=models.CharField(help_text='Default value. Comma separated values supported for checkboxes.', max_length=255, blank=True),
preserve_default=True,
),
]

View file

@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0005_auto_20141113_0642'),
('tests', '0005_auto_20141008_0122'),
]
operations = [
]

View file

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0006_merge'),
]
operations = [
migrations.AlterField(
model_name='pagechoosermodel',
name='page',
field=models.ForeignKey(to='wagtailcore.Page', help_text='help text'),
preserve_default=True,
),
migrations.AlterField(
model_name='snippetchoosermodel',
name='advert',
field=models.ForeignKey(to='tests.Advert', help_text='help text'),
preserve_default=True,
),
]

View file

@ -1,32 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0007_auto_20141118_0925'),
]
operations = [
migrations.CreateModel(
name='RegisterDecorator',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='RegisterFunction',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('tests', '0008_registerdecorator'),
]
operations = [
migrations.CreateModel(
name='EventPageChooserModel',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('page', models.ForeignKey(help_text='more help text', to='tests.EventPage')),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -1,65 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import wagtail.wagtailadmin.taggable
from django.conf import settings
import taggit.managers
import wagtail.wagtailimages.models
class Migration(migrations.Migration):
dependencies = [
('taggit', '0001_initial'),
('tests', '0009_eventpagechoosermodel'),
]
operations = [
migrations.CreateModel(
name='CustomImageWithAdminFormFields',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('title', models.CharField(verbose_name='Title', max_length=255)),
('file', models.ImageField(verbose_name='File', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, width_field='width')),
('width', models.IntegerField(editable=False)),
('height', models.IntegerField(editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('focal_point_x', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_y', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_width', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_height', models.PositiveIntegerField(blank=True, null=True)),
('caption', models.CharField(max_length=255)),
('not_editable_field', models.CharField(max_length=255)),
('tags', taggit.managers.TaggableManager(verbose_name='Tags', help_text=None, through='taggit.TaggedItem', blank=True, to='taggit.Tag')),
('uploaded_by_user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, blank=True, editable=False)),
],
options={
'abstract': False,
},
bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable),
),
migrations.CreateModel(
name='CustomImageWithoutAdminFormFields',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('title', models.CharField(verbose_name='Title', max_length=255)),
('file', models.ImageField(verbose_name='File', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, width_field='width')),
('width', models.IntegerField(editable=False)),
('height', models.IntegerField(editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('focal_point_x', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_y', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_width', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_height', models.PositiveIntegerField(blank=True, null=True)),
('caption', models.CharField(max_length=255)),
('not_editable_field', models.CharField(max_length=255)),
('tags', taggit.managers.TaggableManager(verbose_name='Tags', help_text=None, through='taggit.TaggedItem', blank=True, to='taggit.Tag')),
('uploaded_by_user', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, blank=True, editable=False)),
],
options={
'abstract': False,
},
bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable),
),
]

View file

@ -0,0 +1 @@
default_app_config = 'wagtail.tests.routablepage.apps.WagtailRoutablePageTestsAppConfig'

View file

@ -0,0 +1,7 @@
from django.apps import AppConfig
class WagtailRoutablePageTestsAppConfig(AppConfig):
name = 'wagtail.tests.routablepage'
label = 'routablepagetests'
verbose_name = "Wagtail routable page tests"

View file

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import wagtail.contrib.wagtailroutablepage.models
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0013_update_golive_expire_help_text'),
]
operations = [
migrations.CreateModel(
name='RoutablePageTest',
fields=[
('page_ptr', models.OneToOneField(to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True, parent_link=True)),
],
options={
'abstract': False,
},
bases=(wagtail.contrib.wagtailroutablepage.models.RoutablePageMixin, 'wagtailcore.page'),
),
]

View file

@ -0,0 +1,28 @@
from django.db import models
from django.http import HttpResponse
from django.conf.urls import url
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
def routable_page_external_view(request, arg):
return HttpResponse("EXTERNAL VIEW: " + arg)
class RoutablePageTest(RoutablePage):
@property
def subpage_urls(self):
return (
url(r'^$', self.main, name='main'),
url(r'^archive/year/(\d+)/$', self.archive_by_year, name='archive_by_year'),
url(r'^archive/author/(?P<author_slug>.+)/$', self.archive_by_author, name='archive_by_author'),
url(r'^external/(.+)/$', routable_page_external_view, name='external_view')
)
def archive_by_year(self, request, year):
return HttpResponse("ARCHIVE BY YEAR: " + str(year))
def archive_by_author(self, request, author_slug):
return HttpResponse("ARCHIVE BY AUTHOR: " + author_slug)
def main(self, request):
return HttpResponse("MAIN VIEW")

View file

@ -0,0 +1 @@
default_app_config = 'wagtail.tests.search.apps.WagtailSearchTestsAppConfig'

View file

@ -0,0 +1,7 @@
from django.apps import AppConfig
class WagtailSearchTestsAppConfig(AppConfig):
name = 'wagtail.tests.search'
label = 'searchtests'
verbose_name = "Wagtail search tests"

View file

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import wagtail.wagtailsearch.index
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='SearchTest',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', 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(primary_key=True, serialize=False, parent_link=True, to='searchtests.SearchTest', auto_created=True)),
('subtitle', models.CharField(null=True, max_length=255, blank=True)),
('extra_content', models.TextField()),
],
options={
},
bases=('searchtests.searchtest',),
),
]

View file

@ -0,0 +1,54 @@
from django.db import models
from wagtail.wagtailsearch import index
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 = [
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):
return "Callable"
@classmethod
def get_indexed_objects(cls):
indexed_objects = super(SearchTest, cls).get_indexed_objects()
# Exclude SearchTests that have a SearchTestChild to stop update_index creating duplicates
if cls is SearchTest:
indexed_objects = indexed_objects.exclude(
id__in=SearchTestChild.objects.all().values_list('searchtest_ptr_id', flat=True)
)
# Exclude SearchTests that have the title "Don't index me!"
indexed_objects = indexed_objects.exclude(title="Don't index me!")
return indexed_objects
def get_indexed_instance(self):
# Check if there is a SearchTestChild that descends from this
child = SearchTestChild.objects.filter(searchtest_ptr_id=self.id).first()
# Return the child if there is one, otherwise return self
return child or self
class SearchTestChild(SearchTest):
subtitle = models.CharField(max_length=255, null=True, blank=True)
extra_content = models.TextField()
search_fields = SearchTest.search_fields + [
index.SearchField('subtitle', partial_match=True),
index.SearchField('extra_content'),
]

View file

@ -76,7 +76,12 @@ INSTALLED_APPS = (
'wagtail.contrib.wagtailsitemaps',
'wagtail.contrib.wagtailroutablepage',
'wagtail.contrib.wagtailfrontendcache',
'wagtail.tests',
'wagtail.tests.testapp',
'wagtail.tests.demosite',
'wagtail.tests.customuser',
'wagtail.tests.snippets',
'wagtail.tests.routablepage',
'wagtail.tests.search',
# Install wagtailredirects with its appconfig
# Theres nothing special about wagtailredirects, we just need to have one
@ -110,7 +115,7 @@ WAGTAILSEARCH_BACKENDS = {
}
}
AUTH_USER_MODEL = 'tests.CustomUser'
AUTH_USER_MODEL = 'customuser.CustomUser'
try:
# Only add Elasticsearch backend if the elasticsearch-py library is installed

View file

@ -0,0 +1 @@
default_app_config = 'wagtail.tests.snippets.apps.WagtailSnippetsTestsAppConfig'

View file

@ -0,0 +1,7 @@
from django.apps import AppConfig
class WagtailSnippetsTestsAppConfig(AppConfig):
name = 'wagtail.tests.snippets'
label = 'snippetstests'
verbose_name = "Wagtail snippets tests"

View file

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='AlphaSnippet',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('text', models.CharField(max_length=255)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='RegisterDecorator',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='RegisterFunction',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='ZuluSnippet',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('text', models.CharField(max_length=255)),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -0,0 +1,39 @@
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from wagtail.wagtailsnippets.models import register_snippet
# AlphaSnippet and ZuluSnippet are for testing ordering of
# snippets when registering. They are named as such to ensure
# thier ordering is clear. They are registered during testing
# to ensure specific [in]correct register ordering
# AlphaSnippet is registered during TestSnippetOrdering
@python_2_unicode_compatible
class AlphaSnippet(models.Model):
text = models.CharField(max_length=255)
def __str__(self):
return self.text
# ZuluSnippet is registered during TestSnippetOrdering
@python_2_unicode_compatible
class ZuluSnippet(models.Model):
text = models.CharField(max_length=255)
def __str__(self):
return self.text
# Register model as snippet using register_snippet as both a function and a decorator
class RegisterFunction(models.Model):
pass
register_snippet(RegisterFunction)
@register_snippet
class RegisterDecorator(models.Model):
pass

View file

@ -1,10 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>{{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
{% include "tests/includes/event_listing.html" %}
</body>
</html>

View file

@ -1,17 +0,0 @@
{% load wagtailcore_tags wagtailimages_tags %}
<!DOCTYPE HTML>
<html>
<head>
<title>Event: {{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
<h2>Event</h2>
{% if self.feed_image %}
{% image self.feed_image width-200 class="feed-image" %}
{% endif %}
{{ self.body|richtext }}
<p><a href="{% slugurl 'events' %}">Back to events index</a></p>
</body>
</html>

View file

@ -1,15 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>{{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
<p>This event is invitation only. Please enter your password to see the details.</p>
<form action="{{ action_url }}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Continue" />
</form>
</body>
</html>

View file

@ -1,16 +0,0 @@
{% load wagtailcore_tags %}
<!DOCTYPE HTML>
<html>
<head>
<title>{{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
<form action="{% pageurl self %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
</body>
</html>

View file

@ -1,12 +0,0 @@
{% load wagtailcore_tags %}
<!DOCTYPE HTML>
<html>
<head>
<title>{{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
<p>Thank you for your feedback.</p>
</body>
</html>

View file

@ -1,12 +0,0 @@
{% load wagtailcore_tags %}
<!DOCTYPE HTML>
<html>
<head>
<title>{{ self.title }}</title>
</head>
<body>
<h1>{{ self.title }}</h1>
<h2>Simple page</h2>
</body>
</html>

View file

@ -0,0 +1 @@
default_app_config = 'wagtail.tests.testapp.apps.WagtailTestsAppConfig'

View file

@ -0,0 +1,7 @@
from django.apps import AppConfig
class WagtailTestsAppConfig(AppConfig):
name = 'wagtail.tests.testapp'
label = 'tests'
verbose_name = "Wagtail tests"

View file

@ -461,7 +461,7 @@
},
{
"pk": 1,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "superuser",
"first_name": "",
@ -478,7 +478,7 @@
},
{
"pk": 2,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "eventeditor",
"first_name": "",
@ -496,7 +496,7 @@
},
{
"pk": 3,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "eventmoderator",
"first_name": "",
@ -514,7 +514,7 @@
},
{
"pk": 4,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "inactiveuser",
"first_name": "",
@ -532,7 +532,7 @@
},
{
"pk": 5,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "siteeditor",
"first_name": "",
@ -550,7 +550,7 @@
},
{
"pk": 6,
"model": "tests.customuser",
"model": "customuser.customuser",
"fields": {
"username": "admin_only_user",
"first_name": "",

View file

@ -3,29 +3,31 @@ 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
from django.conf import settings
import modelcluster.tags
import wagtail.wagtailimages.models
import wagtail.wagtailadmin.taggable
import modelcluster.fields
import wagtail.wagtailcore.fields
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0002_initial_data'),
('wagtailcore', '0013_update_golive_expire_help_text'),
('wagtaildocs', '0002_initial_data'),
('taggit', '0001_initial'),
('wagtailimages', '0002_initial_data'),
('tests', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('wagtailimages', '0005_make_filter_spec_unique'),
]
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)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('url', models.URLField(blank=True, null=True)),
('text', models.CharField(max_length=255)),
],
options={
@ -35,27 +37,18 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='AdvertPlacement',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('colour', models.CharField(max_length=255)),
('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)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
@ -65,7 +58,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='BusinessIndex',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
@ -75,17 +68,63 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='BusinessSubIndex',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='CustomImageWithAdminFormFields',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('title', models.CharField(max_length=255, verbose_name='Title')),
('file', models.ImageField(width_field='width', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, verbose_name='File')),
('width', models.IntegerField(editable=False)),
('height', models.IntegerField(editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('focal_point_x', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_y', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_width', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_height', models.PositiveIntegerField(blank=True, null=True)),
('caption', models.CharField(max_length=255)),
('not_editable_field', models.CharField(max_length=255)),
('tags', taggit.managers.TaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='taggit.TaggedItem', help_text=None)),
('uploaded_by_user', models.ForeignKey(null=True, blank=True, to=settings.AUTH_USER_MODEL, editable=False)),
],
options={
'abstract': False,
},
bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable),
),
migrations.CreateModel(
name='CustomImageWithoutAdminFormFields',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('title', models.CharField(max_length=255, verbose_name='Title')),
('file', models.ImageField(width_field='width', height_field='height', upload_to=wagtail.wagtailimages.models.get_upload_to, verbose_name='File')),
('width', models.IntegerField(editable=False)),
('height', models.IntegerField(editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('focal_point_x', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_y', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_width', models.PositiveIntegerField(blank=True, null=True)),
('focal_point_height', models.PositiveIntegerField(blank=True, null=True)),
('caption', models.CharField(max_length=255)),
('not_editable_field', models.CharField(max_length=255)),
('tags', taggit.managers.TaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='taggit.TaggedItem', help_text=None)),
('uploaded_by_user', models.ForeignKey(null=True, blank=True, to=settings.AUTH_USER_MODEL, editable=False)),
],
options={
'abstract': False,
},
bases=(models.Model, wagtail.wagtailadmin.taggable.TagSearchable),
),
migrations.CreateModel(
name='EventIndex',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
('intro', wagtail.wagtailcore.fields.RichTextField(blank=True)),
],
options={
@ -96,17 +135,17 @@ class Migration(migrations.Migration):
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')),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
('date_from', models.DateField(verbose_name='Start date', null=True)),
('date_to', models.DateField(blank=True, help_text='Not required if event is on a single day', verbose_name='End date', null=True)),
('time_from', models.TimeField(blank=True, verbose_name='Start time', null=True)),
('time_to', models.TimeField(blank=True, verbose_name='End time', null=True)),
('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)),
('feed_image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)),
],
options={
'abstract': False,
@ -116,74 +155,84 @@ class Migration(migrations.Migration):
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)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('sort_order', models.IntegerField(editable=False, null=True, blank=True)),
('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)),
('image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)),
],
options={
'abstract': False,
'ordering': ['sort_order'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='EventPageChooserModel',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('page', models.ForeignKey(to='tests.EventPage', help_text='more help text')),
],
options={
},
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)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('sort_order', models.IntegerField(editable=False, null=True, blank=True)),
('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)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)),
],
options={
'abstract': False,
'ordering': ['sort_order'],
'abstract': False,
},
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)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('sort_order', models.IntegerField(editable=False, null=True, blank=True)),
('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)),
('first_name', models.CharField(blank=True, max_length=255, verbose_name='Name')),
('last_name', models.CharField(blank=True, max_length=255, verbose_name='Surname')),
('image', models.ForeignKey(to='wagtailimages.Image', null=True, related_name='+', blank=True, on_delete=django.db.models.deletion.SET_NULL)),
('link_document', models.ForeignKey(to='wagtaildocs.Document', null=True, related_name='+', blank=True)),
],
options={
'abstract': False,
'ordering': ['sort_order'],
'abstract': False,
},
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)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('sort_order', models.IntegerField(editable=False, null=True, blank=True)),
('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)),
('choices', models.CharField(blank=True, help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', max_length=512)),
('default_value', models.CharField(blank=True, help_text='Default value. Comma separated values supported for checkboxes.', max_length=255)),
('help_text', models.CharField(blank=True, max_length=255)),
],
options={
'abstract': False,
'ordering': ['sort_order'],
'abstract': False,
},
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)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
('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)),
@ -193,10 +242,19 @@ class Migration(migrations.Migration):
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='PageChooserModel',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='PageWithOldStyleRouteMethod',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
('content', models.TextField()),
],
options={
@ -204,62 +262,10 @@ class Migration(migrations.Migration):
},
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)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
('content', models.TextField()),
],
options={
@ -267,10 +273,20 @@ class Migration(migrations.Migration):
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='SnippetChooserModel',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('advert', models.ForeignKey(to='tests.Advert', help_text='help text')),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='StandardChild',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
@ -280,7 +296,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='StandardIndex',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
@ -290,7 +306,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='TaggedPage',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, to='wagtailcore.Page', serialize=False, auto_created=True, primary_key=True)),
('page_ptr', models.OneToOneField(parent_link=True, primary_key=True, to='wagtailcore.Page', auto_created=True, serialize=False)),
],
options={
'abstract': False,
@ -300,7 +316,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='TaggedPageTag',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('content_object', modelcluster.fields.ParentalKey(to='tests.TaggedPage', related_name='tagged_items')),
('tag', models.ForeignKey(to='taggit.Tag', related_name='tests_taggedpagetag_items')),
],
@ -309,20 +325,16 @@ class Migration(migrations.Migration):
},
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.'),
field=modelcluster.tags.ClusterTaggableManager(verbose_name='Tags', to='taggit.Tag', blank=True, through='tests.TaggedPageTag', help_text='A comma-separated list of tags.'),
preserve_default=True,
),
migrations.AddField(
model_name='pagechoosermodel',
name='page',
field=models.ForeignKey(to='wagtailcore.Page', help_text='help text'),
preserve_default=True,
),
migrations.AddField(
@ -334,7 +346,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='eventpagespeaker',
name='link_page',
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True),
preserve_default=True,
),
migrations.AddField(
@ -346,7 +358,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='eventpagerelatedlink',
name='link_page',
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True),
preserve_default=True,
),
migrations.AddField(
@ -358,7 +370,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='eventpagecarouselitem',
name='link_page',
field=models.ForeignKey(related_name='+', blank=True, to='wagtailcore.Page', null=True),
field=models.ForeignKey(to='wagtailcore.Page', null=True, related_name='+', blank=True),
preserve_default=True,
),
migrations.AddField(
@ -373,14 +385,4 @@ class Migration(migrations.Migration):
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.'),
),
]

View file

@ -2,10 +2,7 @@ from __future__ import unicode_literals
from django.db import models
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.utils.encoding import python_2_unicode_compatible
from django.conf.urls import url
from django.http import HttpResponse
from taggit.models import TaggedItemBase
@ -17,11 +14,10 @@ from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel, PageChooserPanel, TabbedInterface, ObjectList
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.wagtailforms.models import AbstractEmailForm, AbstractFormField
from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel
from wagtail.wagtailsearch import index
from wagtail.contrib.wagtailroutablepage.models import RoutablePage
from wagtail.wagtailimages.models import AbstractImage, Image
@ -39,50 +35,6 @@ COMMON_PANELS = (
)
class CustomUserManager(BaseUserManager):
def _create_user(self, username, email, password,
is_staff, is_superuser, **extra_fields):
"""
Creates and saves a User with the given username, email and password.
"""
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, False, False,
**extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
return self._create_user(username, email, password, True, True,
**extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=100, unique=True)
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)
USERNAME_FIELD = 'username'
objects = CustomUserManager()
def get_full_name(self):
return self.first_name + ' ' + self.last_name
def get_short_name(self):
return self.first_name
# Link fields
class LinkFields(models.Model):
@ -365,29 +317,6 @@ class Advert(models.Model):
register_snippet(Advert)
# AlphaSnippet and ZuluSnippet are for testing ordering of
# snippets when registering. They are named as such to ensure
# thier ordering is clear. They are registered during testing
# to ensure specific [in]correct register ordering
# AlphaSnippet is registered during TestSnippetOrdering
@python_2_unicode_compatible
class AlphaSnippet(models.Model):
text = models.CharField(max_length=255)
def __str__(self):
return self.text
# ZuluSnippet is registered during TestSnippetOrdering
@python_2_unicode_compatible
class ZuluSnippet(models.Model):
text = models.CharField(max_length=255)
def __str__(self):
return self.text
class StandardIndex(Page):
""" Index for the site, not allowed to be placed anywhere """
parent_page_types = []
@ -432,77 +361,6 @@ class BusinessChild(Page):
parent_page_types = ['tests.BusinessIndex', BusinessSubIndex]
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 = [
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):
return "Callable"
@classmethod
def get_indexed_objects(cls):
indexed_objects = super(SearchTest, cls).get_indexed_objects()
# Exclude SearchTests that have a SearchTestChild to stop update_index creating duplicates
if cls is SearchTest:
indexed_objects = indexed_objects.exclude(
id__in=SearchTestChild.objects.all().values_list('searchtest_ptr_id', flat=True)
)
# Exclude SearchTests that have the title "Don't index me!"
indexed_objects = indexed_objects.exclude(title="Don't index me!")
return indexed_objects
def get_indexed_instance(self):
# Check if there is a SearchTestChild that descends from this
child = SearchTestChild.objects.filter(searchtest_ptr_id=self.id).first()
# Return the child if there is one, otherwise return self
return child or self
class SearchTestChild(SearchTest):
subtitle = models.CharField(max_length=255, null=True, blank=True)
extra_content = models.TextField()
search_fields = SearchTest.search_fields + [
index.SearchField('subtitle', partial_match=True),
index.SearchField('extra_content'),
]
def routable_page_external_view(request, arg):
return HttpResponse("EXTERNAL VIEW: " + arg)
class RoutablePageTest(RoutablePage):
subpage_urls = (
url(r'^$', 'main', name='main'),
url(r'^archive/year/(\d+)/$', 'archive_by_year', name='archive_by_year'),
url(r'^archive/author/(?P<author_slug>.+)/$', 'archive_by_author', name='archive_by_author'),
url(r'^external/(.+)/$', routable_page_external_view, name='external_view')
)
def archive_by_year(self, request, year):
return HttpResponse("ARCHIVE BY YEAR: " + str(year))
def archive_by_author(self, request, author_slug):
return HttpResponse("ARCHIVE BY AUTHOR: " + author_slug)
def main(self, request):
return HttpResponse("MAIN VIEW")
class TaggedPageTag(TaggedItemBase):
content_object = ParentalKey('tests.TaggedPage', related_name='tagged_items')
@ -530,17 +388,6 @@ class SnippetChooserModel(models.Model):
]
# Register model as snippet using register_snippet as both a function and a decorator
class RegisterFunction(models.Model):
pass
register_snippet(RegisterFunction)
@register_snippet
class RegisterDecorator(models.Model):
pass
class CustomImageWithoutAdminFormFields(AbstractImage):
caption = models.CharField(max_length=255)
not_editable_field = models.CharField(max_length=255)

View file

@ -0,0 +1,13 @@
{% load wagtailuserbar %}
<!DOCTYPE HTML>
<html>
<head>
<title>{% block html_title %}{{ self.title }}{% endblock %}</title>
</head>
<body>
{% wagtailuserbar %}
<h1>{{ self.title }}</h1>
{% block content %}{% endblock %}
</body>
</html>

View file

@ -0,0 +1,5 @@
{% extends "tests/base.html" %}
{% block content %}
<h2>Business Child</h2>
{% endblock %}

View file

@ -0,0 +1,5 @@
{% extends "tests/base.html" %}
{% block content %}
{% include "tests/includes/event_listing.html" %}
{% endblock %}

View file

@ -0,0 +1,12 @@
{% extends "tests/base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}
{% block html_title %}Event: {{ self.title }}{% endblock %}
{% block content %}
<h2>Event</h2>
{% if self.feed_image %}
{% image self.feed_image width-200 class="feed-image" %}
{% endif %}
{{ self.body|richtext }}
<p><a href="{% slugurl 'events' %}">Back to events index</a></p>
{% endblock %}

View file

@ -0,0 +1,10 @@
{% extends "tests/base.html" %}
{% block content %}
<p>This event is invitation only. Please enter your password to see the details.</p>
<form action="{{ action_url }}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Continue" />
</form>
{% endblock %}

View file

@ -0,0 +1,10 @@
{% extends "tests/base.html" %}
{% load wagtailcore_tags %}
{% block content %}
<form action="{% pageurl self %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
{% endblock %}

View file

@ -0,0 +1,5 @@
{% extends "tests/base.html" %}
{% block content %}
<p>Thank you for your feedback.</p>
{% endblock %}

View file

@ -0,0 +1,5 @@
{% extends "tests/base.html" %}
{% block content %}
<h2>Simple page</h2>
{% endblock %}

View file

@ -1,101 +0,0 @@
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models import Q
from wagtail.wagtailcore.models import PageRevision, GroupPagePermission
from wagtail.wagtailusers.models import UserProfile
# The following will check to see if we can import task from celery -
# if not then we definitely haven't installed it
try:
from celery.decorators import task
NO_CELERY = False
except:
NO_CELERY = True
# However, we could have installed celery for other projects. So we will also
# check if we have defined the BROKER_URL setting. If not then definitely we
# haven't configured it.
if NO_CELERY or not hasattr(settings, 'BROKER_URL'):
# So if we enter here we will define a different "task" decorator that
# just returns the original function and sets its delay attribute to
# point to the original function: This way, the send_notification
# function will be actually called instead of the the
# send_notification.delay()
def task(f):
f.delay=f
return f
def users_with_page_permission(page, permission_type, include_superusers=True):
# Get user model
User = get_user_model()
# Find GroupPagePermission records of the given type that apply to this page or an ancestor
ancestors_and_self = list(page.get_ancestors()) + [page]
perm = GroupPagePermission.objects.filter(permission_type=permission_type, page__in=ancestors_and_self)
q = Q(groups__page_permissions=perm)
# Include superusers
if include_superusers:
q |= Q(is_superuser=True)
return User.objects.filter(is_active=True).filter(q).distinct()
@task
def send_notification(page_revision_id, notification, excluded_user_id):
# Get revision
revision = PageRevision.objects.get(id=page_revision_id)
# Get list of recipients
if notification == 'submitted':
# Get list of publishers
recipients = users_with_page_permission(revision.page, 'publish')
elif notification in ['rejected', 'approved']:
# Get submitter
recipients = [revision.user]
else:
return
# Get list of email addresses
email_addresses = [
recipient.email for recipient in recipients
if recipient.email and recipient.id != excluded_user_id and getattr(UserProfile.get_for_user(recipient), notification + '_notifications')
]
# Return if there are no email addresses
if not email_addresses:
return
# Get email subject and content
template = 'wagtailadmin/notifications/' + notification + '.html'
rendered_template = render_to_string(template, dict(revision=revision, settings=settings)).split('\n')
email_subject = rendered_template[0]
email_content = '\n'.join(rendered_template[1:])
# Get from email
if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'):
from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL
elif hasattr(settings, 'DEFAULT_FROM_EMAIL'):
from_email = settings.DEFAULT_FROM_EMAIL
else:
from_email = 'webmaster@localhost'
# Send email
send_mail(email_subject, email_content, from_email, email_addresses)
@task
def send_email_task(email_subject, email_content, email_addresses, from_email=None):
if not from_email:
if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'):
from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL
elif hasattr(settings, 'DEFAULT_FROM_EMAIL'):
from_email = settings.DEFAULT_FROM_EMAIL
else:
from_email = 'webmaster@localhost'
send_mail(email_subject, email_content, from_email, email_addresses)

View file

@ -2,5 +2,5 @@
{% load i18n %}
{% block item_content %}
<a href="{% url 'wagtailadmin_pages_add_subpage' self.parent_page.id %}" target="_parent" class="action icon icon-plus" title="{% trans 'Add another page at this level' %}">{% trans 'Add' %}</a>
{% endblock %}
<a href="{% url 'wagtailadmin_pages_add_subpage' self.page.id %}" target="_parent" class="action icon icon-plus" title="{% trans 'Add a child page' %}">{% trans 'Add' %}</a>
{% endblock %}

View file

@ -20,7 +20,7 @@ from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput, Admin
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailcore.models import Page, Site
from wagtail.wagtailcore.fields import RichTextArea
from wagtail.tests.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker, SimplePage
from wagtail.tests.testapp.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker, SimplePage
from wagtail.tests.utils import WagtailTestUtils
from wagtail.utils.deprecation import RemovedInWagtail12Warning

View file

@ -2,7 +2,7 @@ from django.test import TestCase
from django.core.urlresolvers import reverse
from wagtail.wagtailcore.models import Page
from wagtail.tests.models import SimplePage
from wagtail.tests.testapp.models import SimplePage
from wagtail.tests.utils import WagtailTestUtils

View file

@ -11,7 +11,7 @@ from django.core.paginator import Paginator
from django.db.models.signals import pre_delete, post_delete
from django.utils import timezone
from wagtail.tests.models import (
from wagtail.tests.testapp.models import (
SimplePage, EventPage, EventPageCarouselItem,
StandardIndex, StandardChild,
BusinessIndex, BusinessChild, BusinessSubIndex,

View file

@ -2,7 +2,7 @@ from django.test import TestCase
from django.core.urlresolvers import reverse
from wagtail.wagtailcore.models import Page, PageViewRestriction
from wagtail.tests.models import SimplePage
from wagtail.tests.testapp.models import SimplePage
from wagtail.tests.utils import WagtailTestUtils

View file

@ -7,6 +7,7 @@ from django.contrib.auth.models import AnonymousUser
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore.models import Page
from wagtail.tests.testapp.models import BusinessIndex, BusinessChild
class TestUserbarTag(TestCase):
@ -60,6 +61,37 @@ class TestUserbarFrontend(TestCase, WagtailTestUtils):
self.assertEqual(response.status_code, 403)
class TestUserbarAddLink(TestCase, WagtailTestUtils):
fixtures = ['test.json']
def setUp(self):
self.login()
self.homepage = Page.objects.get(url_path='/home/')
self.event_index = Page.objects.get(url_path='/home/events/')
self.business_index = BusinessIndex(title='Business', slug='business', live=True)
self.homepage.add_child(instance=self.business_index)
self.business_child = BusinessChild(title='Business Child', slug='child', live=True)
self.business_index.add_child(instance=self.business_child)
def test_page_allowing_subpages(self):
response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.event_index.id, )))
# page allows subpages, so the 'add page' button should show
expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.event_index.id, ))
expected_link = '<a href="%s" target="_parent" class="action icon icon-plus" title="Add a child page">Add</a>' % expected_url
self.assertContains(response, expected_link)
def test_page_disallowing_subpages(self):
response = self.client.get(reverse('wagtailadmin_userbar_frontend', args=(self.business_child.id, )))
# page disallows subpages, so the 'add page' button shouldn't show
expected_url = reverse('wagtailadmin_pages_add_subpage', args=(self.business_index.id, ))
expected_link = '<a href="%s" target="_parent" class="action icon icon-plus" title="Add a child page">Add</a>' % expected_url
self.assertNotContains(response, expected_link)
class TestUserbarModeration(TestCase, WagtailTestUtils):
def setUp(self):
self.login()

View file

@ -1,10 +1,10 @@
from django.test import TestCase
from django.test import TestCase, override_settings
from django.core.urlresolvers import reverse
from django.core import mail
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.tasks import send_email_task
from wagtail.wagtailadmin.utils import send_mail
class TestHome(TestCase, WagtailTestUtils):
@ -56,15 +56,48 @@ class TestEditorHooks(TestCase, WagtailTestUtils):
self.assertContains(response, '<script src="/path/to/my/custom.js"></script>')
class TestSendEmailTask(TestCase):
class TestSendMail(TestCase):
def test_send_email(self):
send_email_task("Test subject", "Test content", ["nobody@email.com"], "test@email.com")
send_mail("Test subject", "Test content", ["nobody@email.com"], "test@email.com")
# Check that the email was sent
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "Test subject")
self.assertEqual(mail.outbox[0].body, "Test content")
self.assertEqual(mail.outbox[0].to, ["nobody@email.com"])
self.assertEqual(mail.outbox[0].from_email, "test@email.com")
@override_settings(WAGTAILADMIN_NOTIFICATION_FROM_EMAIL='anothertest@email.com')
def test_send_fallback_to_wagtailadmin_notification_from_email_setting(self):
send_mail("Test subject", "Test content", ["nobody@email.com"])
# Check that the email was sent
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "Test subject")
self.assertEqual(mail.outbox[0].body, "Test content")
self.assertEqual(mail.outbox[0].to, ["nobody@email.com"])
self.assertEqual(mail.outbox[0].from_email, "anothertest@email.com")
@override_settings(DEFAULT_FROM_EMAIL='yetanothertest@email.com')
def test_send_fallback_to_default_from_email_setting(self):
send_mail("Test subject", "Test content", ["nobody@email.com"])
# Check that the email was sent
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "Test subject")
self.assertEqual(mail.outbox[0].body, "Test content")
self.assertEqual(mail.outbox[0].to, ["nobody@email.com"])
self.assertEqual(mail.outbox[0].from_email, "yetanothertest@email.com")
def test_send_default_from_email(self):
send_mail("Test subject", "Test content", ["nobody@email.com"])
# Check that the email was sent
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "Test subject")
self.assertEqual(mail.outbox[0].body, "Test content")
self.assertEqual(mail.outbox[0].to, ["nobody@email.com"])
self.assertEqual(mail.outbox[0].from_email, "webmaster@localhost")
class TestExplorerNavView(TestCase, WagtailTestUtils):

View file

@ -23,8 +23,8 @@ class AddPageItem(BaseItem):
if not request.user.has_perm('wagtailadmin.access_admin'):
return ""
# Don't render if user doesn't have ability to add siblings
permission_checker = self.page.get_parent().permissions_for_user(request.user)
# Don't render if user doesn't have ability to add children here
permission_checker = self.page.permissions_for_user(request.user)
if not permission_checker.can_add_subpage():
return ""

View file

@ -1,6 +1,13 @@
from django.template.loader import render_to_string
from django.core.mail import send_mail as django_send_mail
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models import Q
from modelcluster.fields import ParentalKey
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.models import Page, PageRevision, GroupPagePermission
from wagtail.wagtailusers.models import UserProfile
def get_object_usage(obj):
@ -34,3 +41,65 @@ def get_object_usage(obj):
)
return pages
def users_with_page_permission(page, permission_type, include_superusers=True):
# Get user model
User = get_user_model()
# Find GroupPagePermission records of the given type that apply to this page or an ancestor
ancestors_and_self = list(page.get_ancestors()) + [page]
perm = GroupPagePermission.objects.filter(permission_type=permission_type, page__in=ancestors_and_self)
q = Q(groups__page_permissions=perm)
# Include superusers
if include_superusers:
q |= Q(is_superuser=True)
return User.objects.filter(is_active=True).filter(q).distinct()
def send_mail(email_subject, email_content, email_addresses, from_email=None):
if not from_email:
if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'):
from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL
elif hasattr(settings, 'DEFAULT_FROM_EMAIL'):
from_email = settings.DEFAULT_FROM_EMAIL
else:
from_email = 'webmaster@localhost'
django_send_mail(email_subject, email_content, from_email, email_addresses)
def send_notification(page_revision_id, notification, excluded_user_id):
# Get revision
revision = PageRevision.objects.get(id=page_revision_id)
# Get list of recipients
if notification == 'submitted':
# Get list of publishers
recipients = users_with_page_permission(revision.page, 'publish')
elif notification in ['rejected', 'approved']:
# Get submitter
recipients = [revision.user]
else:
return
# Get list of email addresses
email_addresses = [
recipient.email for recipient in recipients
if recipient.email and recipient.id != excluded_user_id and getattr(UserProfile.get_for_user(recipient), notification + '_notifications')
]
# Return if there are no email addresses
if not email_addresses:
return
# Get email subject and content
template = 'wagtailadmin/notifications/' + notification + '.html'
rendered_template = render_to_string(template, dict(revision=revision, settings=settings)).split('\n')
email_subject = rendered_template[0]
email_content = '\n'.join(rendered_template[1:])
# Send email
send_mail(email_subject, email_content, email_addresses)

View file

@ -15,7 +15,8 @@ from django.db.models import Count
from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList
from wagtail.wagtailadmin.forms import SearchForm, CopyForm
from wagtail.wagtailadmin import tasks, signals
from wagtail.wagtailadmin.utils import send_notification
from wagtail.wagtailadmin import signals
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Page, PageRevision, get_navigation_menu_items
@ -225,7 +226,7 @@ def create(request, content_type_app_name, content_type_model_name, parent_page_
messages.success(request, _("Page '{0}' published.").format(page.title))
elif is_submitting:
messages.success(request, _("Page '{0}' submitted for moderation.").format(page.title))
tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id)
send_notification(page.get_latest_revision().id, 'submitted', request.user.id)
else:
messages.success(request, _("Page '{0}' created.").format(page.title))
@ -361,7 +362,7 @@ def edit(request, page_id):
messages.button(reverse('wagtailadmin_pages_view_draft', args=(page_id,)), _('View draft')),
messages.button(reverse('wagtailadmin_pages_edit', args=(page_id,)), _('Edit'))
])
tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id)
send_notification(page.get_latest_revision().id, 'submitted', request.user.id)
else:
messages.success(request, _("Page '{0}' updated.").format(page.title))
@ -782,7 +783,7 @@ def approve_moderation(request, revision_id):
if request.method == 'POST':
revision.approve_moderation()
messages.success(request, _("Page '{0}' published.").format(revision.page.title))
tasks.send_notification.delay(revision.id, 'approved', request.user.id)
send_notification(revision.id, 'approved', request.user.id)
return redirect('wagtailadmin_home')
@ -799,7 +800,7 @@ def reject_moderation(request, revision_id):
if request.method == 'POST':
revision.reject_moderation()
messages.success(request, _("Page '{0}' rejected for publication.").format(revision.page.title))
tasks.send_notification.delay(revision.id, 'rejected', request.user.id)
send_notification(revision.id, 'rejected', request.user.id)
return redirect('wagtailadmin_home')

View file

@ -9,7 +9,7 @@ from django.db import models
from wagtail.wagtailcore.models import Page, PageRevision
from wagtail.wagtailcore.signals import page_published, page_unpublished
from wagtail.tests.models import SimplePage, EventPage
from wagtail.tests.testapp.models import SimplePage, EventPage
class TestFixTreeCommand(TestCase):

View file

@ -11,7 +11,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import get_user_model
from wagtail.wagtailcore.models import Page, Site
from wagtail.tests.models import EventPage, EventIndex, SimplePage, PageWithOldStyleRouteMethod, BusinessIndex, BusinessSubIndex, BusinessChild, StandardIndex
from wagtail.tests.testapp.models import EventPage, EventIndex, SimplePage, PageWithOldStyleRouteMethod, BusinessIndex, BusinessSubIndex, BusinessChild, StandardIndex
class TestSiteRouting(TestCase):

View file

@ -2,7 +2,7 @@ from django.test import TestCase
from django.contrib.auth import get_user_model
from wagtail.wagtailcore.models import Page, UserPagePermissionsProxy
from wagtail.tests.models import EventPage
from wagtail.tests.testapp.models import EventPage
class TestPagePermission(TestCase):

View file

@ -1,7 +1,7 @@
from django.test import TestCase
from wagtail.wagtailcore.models import Page, PageViewRestriction
from wagtail.tests.models import EventPage
from wagtail.tests.testapp.models import EventPage
class TestPageQuerySet(TestCase):

View file

@ -12,7 +12,7 @@ from bs4 import BeautifulSoup
class TestPageLinkHandler(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def test_get_db_attributes(self):
soup = BeautifulSoup(

View file

@ -7,7 +7,7 @@ from django.utils.safestring import SafeString
from wagtail.wagtailcore.models import Page, Site
from wagtail.wagtailcore.templatetags.wagtailcore_tags import richtext
from wagtail.wagtailcore.utils import resolve_model_string
from wagtail.tests.models import SimplePage
from wagtail.tests.testapp.models import SimplePage
class TestPageUrlTags(TestCase):

View file

@ -13,7 +13,7 @@ from django.test.utils import override_settings
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore.models import Page
from wagtail.tests.models import EventPage, EventPageRelatedLink
from wagtail.tests.testapp.models import EventPage, EventPageRelatedLink
from wagtail.wagtaildocs.models import Document
from wagtail.wagtaildocs import models
@ -340,7 +340,7 @@ class TestDocumentFilenameProperties(TestCase):
class TestUsageCount(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.login()
@ -391,7 +391,7 @@ class TestUsageCount(TestCase, WagtailTestUtils):
class TestGetUsage(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.login()
@ -581,7 +581,7 @@ class TestServeView(TestCase):
class TestDocumentRichTextLinkHandler(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def test_get_db_attributes(self):
soup = BeautifulSoup(

View file

@ -76,7 +76,7 @@ OEMBED_ENDPOINTS = {
],
"http://api.instagram.com/oembed": [
"^http://instagr\\.am/p/.+$",
"^http://instagram\\.com/p/.+$"
"^http[s]?://instagram\\.com/p/.+$"
],
"https://www.slideshare.net/api/oembed/2": [
"^http://www\\.slideshare\\.net/.+$"

View file

@ -16,7 +16,7 @@ from django.core.serializers.json import DjangoJSONEncoder
from wagtail.wagtailcore.models import Page, Orderable, UserPagePermissionsProxy, get_page_types
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailadmin import tasks
from wagtail.wagtailadmin.utils import send_mail
from .forms import FormBuilder
@ -194,7 +194,7 @@ class AbstractEmailForm(AbstractForm):
if self.to_address:
content = '\n'.join([x[1].label + ': ' + form.data.get(x[0]) for x in form.fields.items()])
tasks.send_email_task.delay(self.subject, content, [self.to_address], self.from_address,)
send_mail(self.subject, content, [self.to_address], self.from_address,)
class Meta:

View file

@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse
from wagtail.wagtailcore.models import Page
from wagtail.wagtailforms.models import FormSubmission
from wagtail.wagtailforms.forms import FormBuilder
from wagtail.tests.models import FormPage, FormField
from wagtail.tests.testapp.models import FormPage, FormField
class TestFormSubmission(TestCase):

View file

@ -261,7 +261,7 @@ def image_delete(sender, instance, **kwargs):
def get_image_model():
from django.conf import settings
from django.db.models import get_model
from django.apps import apps
try:
app_label, model_name = settings.WAGTAILIMAGES_IMAGE_MODEL.split('.')
@ -270,7 +270,7 @@ def get_image_model():
except ValueError:
raise ImproperlyConfigured("WAGTAILIMAGES_IMAGE_MODEL must be of the form 'app_label.model_name'")
image_model = get_model(app_label, model_name)
image_model = apps.get_model(app_label, model_name)
if image_model is None:
raise ImproperlyConfigured("WAGTAILIMAGES_IMAGE_MODEL refers to model '%s' that has not been installed" % settings.WAGTAILIMAGES_IMAGE_MODEL)
return image_model

View file

@ -13,7 +13,7 @@ from django.db import connection
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore.models import Page
from wagtail.tests.models import EventPage, EventPageCarouselItem
from wagtail.tests.testapp.models import EventPage, EventPageCarouselItem
from wagtail.wagtailimages.models import Rendition, Filter, SourceImageIOError
from wagtail.wagtailimages.rect import Rect
@ -161,7 +161,7 @@ class TestRenditions(TestCase):
class TestUsageCount(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.image = Image.objects.create(
@ -184,7 +184,7 @@ class TestUsageCount(TestCase):
class TestGetUsage(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.image = Image.objects.create(

View file

@ -7,8 +7,6 @@ from wagtail.wagtailimages.rich_text import ImageEmbedHandler
class TestImageEmbedHandler(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
def test_get_db_attributes(self):
soup = BeautifulSoup(
'<b data-id="test-id" data-format="test-format" data-alt="test-alt">foo</b>'

View file

@ -13,7 +13,7 @@ from django.db import models
from taggit.forms import TagField, TagWidget
from wagtail.utils.deprecation import RemovedInWagtail12Warning
from wagtail.tests.models import CustomImageWithAdminFormFields, CustomImageWithoutAdminFormFields
from wagtail.tests.testapp.models import CustomImageWithAdminFormFields, CustomImageWithoutAdminFormFields
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailimages.utils import generate_signature, verify_signature
from wagtail.wagtailimages.rect import Rect

View file

@ -3,6 +3,7 @@ import warnings
from six import string_types
from django.db import models
from django.apps import apps
class Indexed(object):
@ -74,7 +75,7 @@ class Indexed(object):
def get_indexed_models():
return [
model for model in models.get_models()
model for model in apps.get_models()
if issubclass(model, Indexed) and not model._meta.abstract
]

View file

@ -8,7 +8,7 @@ from django.conf import settings
from django.core import management
from wagtail.tests.utils import WagtailTestUtils
from wagtail.tests import models
from wagtail.tests.search import models
from wagtail.wagtailsearch.backends import get_search_backend, InvalidSearchBackendError
from wagtail.wagtailsearch.backends.db import DBSearch

View file

@ -8,7 +8,7 @@ import json
from django.test import TestCase
from django.db.models import Q
from wagtail.tests import models
from wagtail.tests.search import models
from .test_backends import BackendTests
@ -186,7 +186,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.all(), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_none_query_string(self):
@ -194,7 +194,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.all(), None)
# Check it
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'match_all': {}}}}
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'match_all': {}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_filter(self):
@ -202,7 +202,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title="Test"), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_and_filter(self):
@ -210,7 +210,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title="Test", live=True), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'and': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'and': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
# Make sure field filters are sorted (as they can be in any order which may cause false positives)
query = query.to_es()
@ -229,7 +229,7 @@ class TestElasticSearchQuery(TestCase):
field_filters[:] = sorted(field_filters, key=lambda f: list(f['term'].keys())[0])
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'or': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'or': [{'term': {'live_filter': True}}, {'term': {'title_filter': 'Test'}}]}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query, expected_result)
def test_negated_filter(self):
@ -237,7 +237,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.exclude(live=True), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'not': {'term': {'live_filter': True}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'not': {'term': {'live_filter': True}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_fields(self):
@ -245,7 +245,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.all(), "Hello", fields=['title'])
# Check it
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'tests_searchtest'}}, 'query': {'match': {'title': 'Hello'}}}}
expected_result = {'filtered': {'filter': {'prefix': {'content_type': 'searchtests_searchtest'}}, 'query': {'match': {'title': 'Hello'}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_exact_lookup(self):
@ -253,7 +253,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__exact="Test"), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'term': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_none_lookup(self):
@ -261,7 +261,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title=None), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_isnull_true_lookup(self):
@ -269,7 +269,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__isnull=True), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'missing': {'field': 'title_filter'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_isnull_false_lookup(self):
@ -277,7 +277,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__isnull=False), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'not': {'missing': {'field': 'title_filter'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'not': {'missing': {'field': 'title_filter'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_startswith_lookup(self):
@ -285,7 +285,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(title__startswith="Test"), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'prefix': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'prefix': {'title_filter': 'Test'}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_gt_lookup(self):
@ -295,7 +295,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__gt=datetime.datetime(2014, 4, 29)), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_lt_lookup(self):
@ -303,7 +303,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__lt=datetime.datetime(2014, 4, 29)), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'lt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'lt': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_gte_lookup(self):
@ -311,7 +311,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__gte=datetime.datetime(2014, 4, 29)), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_lte_lookup(self):
@ -319,7 +319,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__lte=datetime.datetime(2014, 4, 29)), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'lte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'lte': '2014-04-29'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
def test_range_lookup(self):
@ -330,7 +330,7 @@ class TestElasticSearchQuery(TestCase):
query = self.ElasticSearchQuery(models.SearchTest.objects.filter(published_date__range=(start_date, end_date)), "Hello")
# Check it
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'tests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29', 'lte': '2014-08-19'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
expected_result = {'filtered': {'filter': {'and': [{'prefix': {'content_type': 'searchtests_searchtest'}}, {'range': {'published_date_filter': {'gte': '2014-04-29', 'lte': '2014-08-19'}}}]}, 'query': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query.to_es(), expected_result)
@ -358,7 +358,7 @@ class TestElasticSearchMapping(TestCase):
self.obj.save()
def test_get_document_type(self):
self.assertEqual(self.es_mapping.get_document_type(), 'tests_searchtest')
self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest')
def test_get_mapping(self):
# Build mapping
@ -366,7 +366,7 @@ class TestElasticSearchMapping(TestCase):
# Check
expected_result = {
'tests_searchtest': {
'searchtests_searchtest': {
'properties': {
'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
@ -384,7 +384,7 @@ class TestElasticSearchMapping(TestCase):
self.assertDictEqual(mapping, expected_result)
def test_get_document_id(self):
self.assertEqual(self.es_mapping.get_document_id(self.obj), 'tests_searchtest:' + str(self.obj.pk))
self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))
def test_get_document(self):
# Get document
@ -393,7 +393,7 @@ class TestElasticSearchMapping(TestCase):
# Check
expected_result = {
'pk': str(self.obj.pk),
'content_type': 'tests_searchtest',
'content_type': 'searchtests_searchtest',
'_partials': ['Hello'],
'live_filter': False,
'published_date_filter': None,
@ -430,7 +430,7 @@ class TestElasticSearchMappingInheritance(TestCase):
self.obj.save()
def test_get_document_type(self):
self.assertEqual(self.es_mapping.get_document_type(), 'tests_searchtest_tests_searchtestchild')
self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest_searchtests_searchtestchild')
def test_get_mapping(self):
# Build mapping
@ -438,7 +438,7 @@ class TestElasticSearchMappingInheritance(TestCase):
# Check
expected_result = {
'tests_searchtest_tests_searchtestchild': {
'searchtests_searchtest_searchtests_searchtestchild': {
'properties': {
# New
'extra_content': {'type': 'string', 'include_in_all': True},
@ -464,7 +464,7 @@ class TestElasticSearchMappingInheritance(TestCase):
# This must be tests_searchtest instead of 'tests_searchtest_tests_searchtestchild'
# as it uses the contents base content type name.
# This prevents the same object being accidentally indexed twice.
self.assertEqual(self.es_mapping.get_document_id(self.obj), 'tests_searchtest:' + str(self.obj.pk))
self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))
def test_get_document(self):
# Build document
@ -481,7 +481,7 @@ class TestElasticSearchMappingInheritance(TestCase):
'subtitle': 'World',
# Changed
'content_type': 'tests_searchtest_tests_searchtestchild',
'content_type': 'searchtests_searchtest_searchtests_searchtestchild',
# Inherited
'pk': str(self.obj.pk),

View file

@ -5,7 +5,7 @@ from django.core import paginator
from wagtail.wagtailcore.models import Page
from wagtail.wagtailsearch.models import Query
from wagtail.tests.models import EventPage
from wagtail.tests.testapp.models import EventPage
class TestSearchView(TestCase):

View file

@ -3,18 +3,18 @@ import warnings
from django.test import TestCase
from wagtail.wagtailsearch import index
from wagtail.tests import models
from wagtail.tests.search import models
from wagtail.tests.utils import WagtailTestUtils
class TestContentTypeNames(TestCase):
def test_base_content_type_name(self):
name = models.SearchTestChild.indexed_get_toplevel_content_type()
self.assertEqual(name, 'tests_searchtest')
self.assertEqual(name, 'searchtests_searchtest')
def test_qualified_content_type_name(self):
name = models.SearchTestChild.indexed_get_content_type()
self.assertEqual(name, 'tests_searchtest_tests_searchtestchild')
self.assertEqual(name, 'searchtests_searchtest_searchtests_searchtestchild')
class TestSearchFields(TestCase):

View file

@ -1,7 +1,7 @@
from django.test import TestCase
from wagtail.wagtailsearch import signal_handlers
from wagtail.tests import models
from wagtail.tests.search import models
class TestGetIndexedInstance(TestCase):

View file

@ -2,10 +2,11 @@ from django.http import Http404
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.db import models
from django.test.utils import override_settings
from wagtail.tests.utils import WagtailTestUtils
from django.test.utils import override_settings
from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet, SnippetChooserModel, RegisterDecorator, RegisterFunction
from wagtail.tests.testapp.models import Advert, SnippetChooserModel
from wagtail.tests.snippets.models import AlphaSnippet, ZuluSnippet, RegisterDecorator, RegisterFunction
from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS
from wagtail.wagtailsnippets.views.snippets import (
@ -91,7 +92,7 @@ class TestSnippetCreateView(TestCase, WagtailTestUtils):
class TestSnippetEditView(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.test_snippet = Advert.objects.get(id=1)
@ -138,7 +139,7 @@ class TestSnippetEditView(TestCase, WagtailTestUtils):
class TestSnippetDelete(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.test_snippet = Advert.objects.get(id=1)
@ -160,7 +161,7 @@ class TestSnippetDelete(TestCase, WagtailTestUtils):
class TestSnippetChooserPanel(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
model = SnippetChooserModel
@ -213,7 +214,7 @@ class TestSnippetOrdering(TestCase):
class TestUsageCount(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
def test_snippet_usage_count(self):
@ -222,7 +223,7 @@ class TestUsageCount(TestCase):
class TestUsedBy(TestCase):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
def test_snippet_used_by(self):
@ -231,7 +232,7 @@ class TestUsedBy(TestCase):
class TestSnippetChoose(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.login()
@ -255,7 +256,7 @@ class TestSnippetChoose(TestCase, WagtailTestUtils):
class TestSnippetChosen(TestCase, WagtailTestUtils):
fixtures = ['wagtail/tests/fixtures/test.json']
fixtures = ['test.json']
def setUp(self):
self.login()