Merge branch 'master' into feature/settings-menu

pull/664/head
Matt Westcott 2014-09-26 16:05:03 +01:00
commit a8a46b45f5
15 zmienionych plików z 71 dodań i 205 usunięć

Wyświetl plik

@ -8,6 +8,9 @@ Changelog
* Page copy operations now also copy the page revision history
* Page models now support a 'parent_page_types' property in addition to 'subpage types', to restrict the types of page they can be created under
* 'register_snippet' can now be invoked as a decorator
* Project template updated to Django 1.7
* Fix: 'wagtail start' command now works on Windows
* Fix: The external image URL generator no longer stores generated images in Django's cache
0.6 (11.09.2014)
~~~~~~~~~~~~~~~~

Wyświetl plik

@ -64,7 +64,6 @@ You will now be able to run the following command to set up an initial file stru
cd myprojectname
pip install -r requirements.txt
python manage.py syncdb
python manage.py migrate
python manage.py runserver

Wyświetl plik

@ -21,10 +21,14 @@ Minor features
* Page copy operations now also copy the page revision history.
* Page models now support a ``parent_page_types`` property in addition to ``subpage types``, to restrict the types of page they can be created under.
* ``register_snippet`` can now be invoked as a decorator.
* The project template (used when running ``wagtail start``) has been updated to Django 1.7.
Bug fixes
~~~~~~~~~
* The 'wagtail start' command now works on Windows and other environments where the ``django-admin.py`` executable is not readily accessible.
* The external image URL generator no longer stores generated images in Django's cache; this was an unintentional side-effect of setting cache control headers.
Upgrade considerations
======================

Wyświetl plik

@ -33,7 +33,7 @@ install_requires = [
"django-compressor>=1.4",
"django-libsass>=0.2",
"django-modelcluster>=0.4",
"django-taggit==0.12.1",
"django-taggit==0.12.2",
"django-treebeard==2.0",
"Pillow>=2.3.0",
"beautifulsoup4>=4.3.2",
@ -62,7 +62,7 @@ setup(
license='BSD',
long_description=open('README.rst').read(),
classifiers=[
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',

Wyświetl plik

@ -2,11 +2,11 @@
from __future__ import print_function, absolute_import
import os
import subprocess
import errno
import sys
from optparse import OptionParser
from django.core.management import ManagementUtility
def create_project(parser, options, args):
@ -44,15 +44,15 @@ def create_project(parser, options, args):
template_path = os.path.join(wagtail_path, 'project_template')
# Call django-admin startproject
result = subprocess.call([
utility = ManagementUtility([
'django-admin.py', 'startproject',
'--template=' + template_path,
'--name=Vagrantfile', '--ext=html,rst',
project_name
])
utility.execute()
if result == 0:
print("Success! %(project_name)s is created" % {'project_name': project_name})
print("Success! %(project_name)s is created" % {'project_name': project_name})
COMMANDS = {

Wyświetl plik

@ -1,87 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from django.db import models, migrations
class Migration(SchemaMigration):
class Migration(migrations.Migration):
def forwards(self, orm):
# Adding model 'HomePage'
db.create_table('core_homepage', (
('page_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['wagtailcore.Page'], unique=True, primary_key=True)),
))
db.send_create_signal('core', ['HomePage'])
dependencies = [
('wagtailcore', '0002_initial_data'),
]
def backwards(self, orm):
# Deleting model 'HomePage'
db.delete_table('core_homepage')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.homepage': {
'Meta': {'object_name': 'HomePage', '_ormbases': ['wagtailcore.Page']},
'page_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['wagtailcore.Page']", 'unique': 'True', 'primary_key': 'True'})
},
'wagtailcore.page': {
'Meta': {'object_name': 'Page'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}),
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
}
}
complete_apps = ['core']
operations = [
migrations.CreateModel(
name='HomePage',
fields=[
('page_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
]

Wyświetl plik

@ -1,114 +1,45 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models, connection
from django.db.transaction import set_autocommit
from django.db import models, migrations
class Migration(DataMigration):
def create_homepage(apps, schema_editor):
# Get models
ContentType = apps.get_model('contenttypes.ContentType')
Page = apps.get_model('wagtailcore.Page')
Site = apps.get_model('wagtailcore.Site')
HomePage = apps.get_model('core.HomePage')
depends_on = (
('wagtailcore', '0002_initial_data'),
# Delete the default homepage
Page.objects.get(id=2).delete()
# Create content type for homepage model
homepage_content_type, created = ContentType.objects.get_or_create(
model='homepage', app_label='core', defaults={'name': 'Homepage'})
# Create a new homepage
homepage = HomePage.objects.create(
title="Homepage",
slug='home',
content_type=homepage_content_type,
path='00010001',
depth=2,
numchild=0,
url_path='/home/',
)
def forwards(self, orm):
if connection.vendor == 'sqlite':
set_autocommit(True)
# Create a site with the new homepage set as the root
Site.objects.create(
hostname='localhost', root_page=homepage, is_default_site=True)
orm['wagtailcore.Page'].objects.get(id=2).delete()
homepage_content_type, created = orm['contenttypes.contenttype'].objects.get_or_create(
model='homepage', app_label='core', defaults={'name': 'Homepage'})
class Migration(migrations.Migration):
homepage = orm['core.HomePage'].objects.create(
title="Homepage",
slug='home',
content_type=homepage_content_type,
path='00010001',
depth=2,
numchild=0,
url_path='/home/',
)
dependencies = [
('core', '0001_initial'),
]
orm['wagtailcore.site'].objects.create(
hostname='localhost', root_page=homepage, is_default_site=True)
def backwards(self, orm):
pass
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.homepage': {
'Meta': {'object_name': 'HomePage', '_ormbases': ['wagtailcore.Page']},
'page_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['wagtailcore.Page']", 'unique': 'True', 'primary_key': 'True'})
},
'wagtailcore.page': {
'Meta': {'object_name': 'Page'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['contenttypes.ContentType']"}),
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
'expire_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'expired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'go_live_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'has_unpublished_changes': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'live': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_pages'", 'null': 'True', 'to': "orm['auth.User']"}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'search_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'seo_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'show_in_menus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
},
'wagtailcore.site': {
'Meta': {'unique_together': "(('hostname', 'port'),)", 'object_name': 'Site'},
'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_default_site': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'port': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
'root_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sites_rooted_here'", 'to': "orm['wagtailcore.Page']"})
}
}
complete_apps = ['core']
symmetrical = True
operations = [
migrations.RunPython(create_homepage),
]

Wyświetl plik

@ -3,7 +3,6 @@
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />

Wyświetl plik

@ -5,7 +5,6 @@
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />

Wyświetl plik

@ -38,7 +38,6 @@ INSTALLED_APPS = (
'django.contrib.messages',
'django.contrib.staticfiles',
'south',
'compressor',
'taggit',
'modelcluster',

Wyświetl plik

@ -1,6 +1,5 @@
# Minimal requirements
Django>=1.6.2,<1.7
South==1.0.0
Django>=1.7,<1.8
wagtail==0.6
# Recommended components (require additional setup):

Wyświetl plik

@ -22,8 +22,7 @@ chmod a+x $PROJECT_DIR/manage.py
# Run syncdb/migrate/update_index
su - vagrant -c "$PYTHON $PROJECT_DIR/manage.py syncdb --noinput && \
$PYTHON $PROJECT_DIR/manage.py migrate --noinput && \
su - vagrant -c "$PYTHON $PROJECT_DIR/manage.py migrate --noinput && \
$PYTHON $PROJECT_DIR/manage.py update_index"

Wyświetl plik

@ -122,7 +122,7 @@ function InlinePanel(opts) {
var self = {};
self.setHasContent = function(){
if($('li:visible', self.formsUl).length){
if($('> li', self.formsUl).not(".deleted").length){
self.formsUl.parent().removeClass('empty');
}else{
self.formsUl.parent().addClass('empty');
@ -139,7 +139,7 @@ function InlinePanel(opts) {
$('#' + deleteInputId + '-button').click(function() {
/* set 'deleted' form field to true */
$('#' + deleteInputId).val('1');
$('#' + childId).slideUp(function() {
$('#' + childId).addClass('deleted').slideUp(function() {
self.updateMoveButtonDisabledStates();
self.setHasContent();
});
@ -191,8 +191,8 @@ function InlinePanel(opts) {
/* Hide container on page load if it is marked as deleted. Remove the error
message so that it doesn't count towards the number of errors on the tab at the
top of the page. */
if ( $('#' + deleteInputId).val() === "1" ) {
$('#' + childId).hide(0, function() {
if ($('#' + deleteInputId).val() === "1" ) {
$('#' + childId).addClass('deleted').hide(0, function() {
self.updateMoveButtonDisabledStates();
self.setHasContent();
});

Wyświetl plik

@ -783,9 +783,6 @@ class TestFrontendServeView(TestCase):
self.assertEqual(response['Cache-Control'].split('=')[0], 'max-age')
self.assertTrue(int(response['Cache-Control'].split('=')[1]) > datetime.timedelta(days=30).seconds)
self.assertIn('Expires', response)
self.assertTrue(dateutil.parser.parse(response['Expires']) > timezone.now() + datetime.timedelta(days=30))
def test_get_invalid_signature(self):
"""
Test that an invalid signature returns a 403 response

Wyświetl plik

@ -1,13 +1,13 @@
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from django.core.exceptions import PermissionDenied
from django.views.decorators.cache import cache_page
from django.views.decorators.cache import cache_control
from wagtail.wagtailimages.models import get_image_model, Filter
from wagtail.wagtailimages.utils.crypto import verify_signature
@cache_page(60 * 60 * 24 * 60) # Cache for 60 days
@cache_control(max_age=60*60*24*60) # Cache for 60 days
def serve(request, signature, image_id, filter_spec):
image = get_object_or_404(get_image_model(), id=image_id)