mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-12 17:23:15 +00:00
Merge branch 'master' of github.com:torchbox/wagtail into feature/streamfield
Conflicts: wagtail/wagtailadmin/templates/wagtailadmin/shared/field.html
This commit is contained in:
commit
d536fc8315
37 changed files with 294 additions and 121 deletions
|
|
@ -9,12 +9,14 @@ Changelog
|
|||
* Added thousands separator for counters on dashboard
|
||||
* Added contextual links to admin notification messages
|
||||
* When copying pages, it is now possible to specify a place to copy to (Timo Rieber)
|
||||
* FieldPanel now accepts an optional 'widget' parameter to override the field's default form widget (Alejandro Giacometti)
|
||||
|
||||
|
||||
0.8.5 (xx.xx.20xx)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
* Fix: On adding a new page, the available page types are ordered by the displayed verbose name
|
||||
* Fix: Active admin submenus were not properly closed when activating another
|
||||
* Fix: get_sitemap_urls is now called on the specific page class so it can now be overridden (Jerel Unruh)
|
||||
|
||||
|
||||
0.8.4 (04.12.2014)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ Contributors
|
|||
* Robert Rollins
|
||||
* linibou
|
||||
* Timo Rieber
|
||||
* Jerel Unruh
|
||||
|
||||
Translators
|
||||
===========
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ A "panel" is the basic editing block in Wagtail. Wagtail will automatically pick
|
|||
|
||||
There are four basic types of panels:
|
||||
|
||||
``FieldPanel( field_name, classname=None )``
|
||||
This is the panel used for basic Django field types. ``field_name`` is the name of the class property used in your model definition. ``classname`` is a string of optional CSS classes given to the panel which are used in formatting and scripted interactivity. By default, panels are formatted as inset fields. The CSS class ``full`` can be used to format the panel so it covers the full width of the Wagtail page editor. The CSS class ``title`` can be used to mark a field as the source for auto-generated slug strings.
|
||||
``FieldPanel( field_name, classname=None, widget=None )``
|
||||
This is the panel used for basic Django field types. ``field_name`` is the name of the class property used in your model definition. ``classname`` is a string of optional CSS classes given to the panel which are used in formatting and scripted interactivity. By default, panels are formatted as inset fields. The CSS class ``full`` can be used to format the panel so it covers the full width of the Wagtail page editor. The CSS class ``title`` can be used to mark a field as the source for auto-generated slug strings. The optional ``widget`` parameter allows you to specify a `django form widget`_ to use instead of the default widget for this field type.
|
||||
|
||||
.. _django form widget: https://docs.djangoproject.com/en/dev/ref/forms/widgets/
|
||||
|
||||
``MultiFieldPanel( children, heading="", classname=None )``
|
||||
This panel condenses several ``FieldPanel`` s or choosers, from a list or tuple, under a single ``heading`` string.
|
||||
|
|
|
|||
|
|
@ -15,3 +15,4 @@ Bug fixes
|
|||
|
||||
* On adding a new page, the available page types are ordered by the displayed verbose name
|
||||
* Active admin submenus were not properly closed when activating another
|
||||
* ``get_sitemap_urls`` is now called on the specific page class so it can now be overridden
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ Minor features
|
|||
* Added thousands separator for counters on dashboard
|
||||
* Added contextual links to admin notification messages
|
||||
* When copying pages, it is now possible to specify a place to copy to
|
||||
* ``FieldPanel`` now accepts an optional ``widget`` parameter to override the field's default form widget
|
||||
|
||||
|
||||
Bug fixes
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -40,6 +40,7 @@ install_requires = [
|
|||
"Unidecode>=0.04.14",
|
||||
"six>=1.7.0",
|
||||
'requests>=2.0.0',
|
||||
"Willow==0.1",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
1
tox.ini
1
tox.ini
|
|
@ -17,6 +17,7 @@ base =
|
|||
python-dateutil==2.2
|
||||
pytz==2014.7
|
||||
Embedly
|
||||
Willow==0.1
|
||||
coverage
|
||||
|
||||
dj17 =
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class Sitemap(object):
|
|||
|
||||
def get_urls(self):
|
||||
for page in self.get_pages():
|
||||
for url in page.get_sitemap_urls():
|
||||
for url in page.specific.get_sitemap_urls():
|
||||
yield url
|
||||
|
||||
def render(self):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
from wagtail.tests.models import SimplePage, EventIndex
|
||||
|
||||
from .sitemap_generator import Sitemap
|
||||
|
||||
|
|
@ -47,6 +47,20 @@ class TestSitemapGenerator(TestCase):
|
|||
self.assertIn('http://localhost/', urls) # Homepage
|
||||
self.assertIn('http://localhost/hello-world/', urls) # Child page
|
||||
|
||||
def test_get_urls_uses_specific(self):
|
||||
# Add an event page which has an extra url in the sitemap
|
||||
events_page = self.home_page.add_child(instance=EventIndex(
|
||||
title="Events",
|
||||
slug='events',
|
||||
live=True,
|
||||
))
|
||||
|
||||
sitemap = Sitemap(self.site)
|
||||
urls = [url['location'] for url in sitemap.get_urls()]
|
||||
|
||||
self.assertIn('http://localhost/events/', urls) # Main view
|
||||
self.assertIn('http://localhost/events/past/', urls) # Sub view
|
||||
|
||||
def test_render(self):
|
||||
sitemap = Sitemap(self.site)
|
||||
xml = sitemap.render()
|
||||
|
|
|
|||
|
|
@ -306,6 +306,15 @@ class EventIndex(Page):
|
|||
for path in super(EventIndex, self).get_static_site_paths():
|
||||
yield path
|
||||
|
||||
def get_sitemap_urls(self):
|
||||
# Add past events url to sitemap
|
||||
return super(EventIndex, self).get_sitemap_urls() + [
|
||||
{
|
||||
'location': self.full_url + 'past/',
|
||||
'lastmod': self.latest_revision_created_at
|
||||
}
|
||||
]
|
||||
|
||||
EventIndex.content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
FieldPanel('intro', classname="full"),
|
||||
|
|
|
|||
|
|
@ -362,6 +362,15 @@ def MultiFieldPanel(children, heading="", classname=""):
|
|||
|
||||
|
||||
class BaseFieldPanel(EditHandler):
|
||||
|
||||
@classmethod
|
||||
def widget_overrides(cls):
|
||||
"""check if a specific widget has been defined for this field"""
|
||||
if hasattr(cls, 'widget'):
|
||||
return {cls.field_name: cls.widget}
|
||||
else:
|
||||
return {}
|
||||
|
||||
def __init__(self, instance=None, form=None):
|
||||
super(BaseFieldPanel, self).__init__(instance=instance, form=form)
|
||||
self.bound_field = self.form[self.field_name]
|
||||
|
|
@ -408,11 +417,16 @@ class BaseFieldPanel(EditHandler):
|
|||
return [self.field_name]
|
||||
|
||||
|
||||
def FieldPanel(field_name, classname=""):
|
||||
return type(str('_FieldPanel'), (BaseFieldPanel,), {
|
||||
def FieldPanel(field_name, classname="", widget=None):
|
||||
base = {
|
||||
'field_name': field_name,
|
||||
'classname': classname,
|
||||
})
|
||||
}
|
||||
|
||||
if widget:
|
||||
base['widget'] = widget
|
||||
|
||||
return type(str('_FieldPanel'), (BaseFieldPanel,), base)
|
||||
|
||||
|
||||
class BaseRichTextFieldPanel(BaseFieldPanel):
|
||||
|
|
|
|||
|
|
@ -225,13 +225,16 @@ a.tag:hover{
|
|||
}
|
||||
}
|
||||
|
||||
hr{
|
||||
border:1px solid $color-grey-4;
|
||||
border-width:1px 0 0;
|
||||
margin:1.5em 0;
|
||||
}
|
||||
|
||||
/* general image style */
|
||||
img{
|
||||
max-width:100%;
|
||||
height:auto;
|
||||
border: 3px solid $color-grey-4;
|
||||
|
||||
}
|
||||
|
||||
/* make a block-level element inline */
|
||||
|
|
|
|||
|
|
@ -803,8 +803,7 @@ input[type=submit], input[type=reset], input[type=button], .button, button{
|
|||
.boolean_field &,
|
||||
.choice_field &,
|
||||
.model_choice_field &,
|
||||
.image_field &,
|
||||
.file_field &{
|
||||
.image_field &{
|
||||
padding-top:0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -353,6 +353,11 @@ ul.listing{
|
|||
font-size:1em;
|
||||
opacity:0.7;
|
||||
}
|
||||
|
||||
&.images img{
|
||||
@include transition(border-color 0.2s ease);
|
||||
border: 3px solid transparent;
|
||||
}
|
||||
}
|
||||
ul.listing{
|
||||
border-top:1px dashed $color-input-border;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@
|
|||
content:"w";
|
||||
margin-right:0.5em;
|
||||
font-size:1.2em;
|
||||
font-weight:normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,22 @@ kbd{
|
|||
padding:0.3em 0.5em;
|
||||
}
|
||||
|
||||
dl, dt, dd{
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
dl{
|
||||
margin-top:1em;
|
||||
}
|
||||
dt{
|
||||
color:darken($color-grey-3, 5%);
|
||||
text-transform:uppercase;
|
||||
font-size:0.9em;
|
||||
}
|
||||
dd{
|
||||
margin-bottom:1em;
|
||||
}
|
||||
|
||||
/* Help text formatters */
|
||||
|
||||
.help-block{
|
||||
|
|
|
|||
|
|
@ -314,6 +314,13 @@ footer, .logo{
|
|||
@include column(12);
|
||||
}
|
||||
|
||||
.divider-before{
|
||||
border-left:1px solid $color-grey-4;
|
||||
}
|
||||
.divider-after{
|
||||
border-right:1px solid $color-grey-4;
|
||||
}
|
||||
|
||||
.row{
|
||||
@include row();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"metadata": {
|
||||
"name": "Wagtail 1",
|
||||
"lastOpened": 1410881728324,
|
||||
"name": "Wagtail",
|
||||
"lastOpened": 1420801397108,
|
||||
"created": 1405597423787
|
||||
},
|
||||
"iconSets": [
|
||||
|
|
@ -8564,20 +8564,23 @@
|
|||
"minorVersion": 0
|
||||
},
|
||||
"metrics": {
|
||||
"emSize": 512,
|
||||
"emSize": 1024,
|
||||
"baseline": 6.25,
|
||||
"whitespace": 50
|
||||
},
|
||||
"showMetrics": false,
|
||||
"showMetrics": true,
|
||||
"showMetadata": false,
|
||||
"showVersion": false
|
||||
"showVersion": false,
|
||||
"includeMetadata": false
|
||||
},
|
||||
"imagePref": {},
|
||||
"historySize": 100,
|
||||
"showCodes": true,
|
||||
"search": "",
|
||||
"gridSize": 16,
|
||||
"showGrid": true
|
||||
"showGrid": true,
|
||||
"showQuickUse2": true,
|
||||
"showSVGs": true
|
||||
},
|
||||
"externalSets": []
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 62 KiB |
Binary file not shown.
Binary file not shown.
|
|
@ -110,6 +110,8 @@
|
|||
margin:0;
|
||||
cursor:pointer;
|
||||
background-color:$color-salmon;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
<li id="inline_child_{{ child.form.prefix }}">
|
||||
<ul class="controls">
|
||||
{% if can_order %}
|
||||
<li class="icon text-replace white icon-order-up inline-child-move-up" id="{{ child.form.prefix }}-move-up">{% trans "Move up" %}</li>
|
||||
<li class="icon text-replace white icon-order-down inline-child-move-down" id="{{ child.form.prefix }}-move-down">{% trans "Move down" %}</li>
|
||||
<li class="icon text-replace white icon-order-up inline-child-move-up" id="{{ child.form.prefix }}-move-up" title="{% trans 'Move up' %}">{% trans "Move up" %}</li>
|
||||
<li class="icon text-replace white icon-order-down inline-child-move-down" id="{{ child.form.prefix }}-move-down" title="{% trans 'Move down' %}">{% trans "Move down" %}</li>
|
||||
{% endif %}
|
||||
<li class="icon text-replace white icon-bin" id="{{ child.form.DELETE.id_for_label }}-button">{% trans "Delete" %}</li>
|
||||
<li class="icon text-replace white icon-bin" id="{{ child.form.DELETE.id_for_label }}-button" title="{% trans 'Delete' %}">{% trans "Delete" %}</li>
|
||||
</ul>
|
||||
{{ child.render_form_content }}
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block titletag %}{% blocktrans with page_type=content_type.model_class.get_verbose_name %}New {{ page_type }}{% endblocktrans %}{% endblock %}
|
||||
{% block bodyclass %}menu-explorer page-editor create{% endblock %}
|
||||
{% block bodyclass %}menu-explorer page-editor create model-{{ content_type.model }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
|
@ -66,4 +66,10 @@
|
|||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
{% include "wagtailadmin/pages/_editor_js.html" %}
|
||||
|
||||
<script>
|
||||
$(function(){
|
||||
$('#page-edit-form .tab-content section.active input').first().focus();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
{% load gravatar %}
|
||||
{% load i18n %}
|
||||
{% block titletag %}{% blocktrans with title=page.title %}Editing {{ title }}{% endblocktrans %}{% endblock %}
|
||||
{% block bodyclass %}menu-explorer page-editor{% endblock %}
|
||||
{% block titletag %}{% blocktrans with title=page.title page_type=content_type.model_class.get_verbose_name %}Editing {{ page_type }}: {{ title }}{% endblocktrans %}{% endblock %}
|
||||
{% block bodyclass %}menu-explorer page-editor model-{{ content_type.model }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% page_permissions page as page_perms %}
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<div class="row row-flush">
|
||||
<div class="left col9">
|
||||
<h1 class="icon icon-doc-empty-inverse">{% blocktrans with title=page.title %}Editing <span>{{ title }}</span>{% endblocktrans %}</h1>
|
||||
<h1 class="icon icon-doc-empty-inverse">{% blocktrans with title=page.title page_type=content_type.model_class.get_verbose_name %}Editing {{ page_type }} <span>{{ title }}</span>{% endblocktrans %}</h1>
|
||||
</div>
|
||||
<div class="right col3">
|
||||
{% trans "Status" %}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
<div class="field {{ field|fieldtype }} {{ field_classes }}">
|
||||
<div class="field {{ field|fieldtype }} {{ field|widgettype }} {{ field_classes }}">
|
||||
{{ field.label_tag }}
|
||||
<div class="field-content">
|
||||
<div class="input {{ input_classes }} ">
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ def fieldtype(bound_field):
|
|||
return ""
|
||||
|
||||
|
||||
@register.filter
|
||||
def widgettype(bound_field):
|
||||
try:
|
||||
return camelcase_to_underscore(bound_field.field.widget.__class__.__name__)
|
||||
except AttributeError:
|
||||
return ""
|
||||
|
||||
|
||||
@register.filter
|
||||
def meta_description(model):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -255,6 +255,8 @@ def edit(request, page_id):
|
|||
page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
|
||||
parent = page.get_parent()
|
||||
|
||||
content_type = ContentType.objects.get_for_model(page)
|
||||
|
||||
page_perms = page.permissions_for_user(request.user)
|
||||
if not page_perms.can_edit():
|
||||
raise PermissionDenied
|
||||
|
|
@ -373,6 +375,7 @@ def edit(request, page_id):
|
|||
|
||||
return render(request, 'wagtailadmin/pages/edit.html', {
|
||||
'page': page,
|
||||
'content_type': content_type,
|
||||
'edit_handler': edit_handler,
|
||||
'errors_debug': errors_debug,
|
||||
'preview_modes': page.preview_modes,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "wagtailadmin/shared/field_as_li.html" %}
|
||||
{% extends "wagtailadmin/shared/field.html" %}
|
||||
{% load i18n %}
|
||||
{% block form_field %}
|
||||
<a href="{{ document.url }}" class="icon icon-doc-full-inverse">{{ document.file }}</a><br /><br />
|
||||
<a href="{{ document.url }}" class="icon icon-doc-full-inverse">{{ document.filename }}</a><br /><br />
|
||||
{% trans "Change document:" %}
|
||||
{{ field }}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
<li class="{% if field.field.required %}required{% endif %} {{ wrapper_classes }} {{ li_classes }} {% if field.errors %}error{% endif %}">
|
||||
{% include "wagtaildocs/documents/_file_field.html" %}
|
||||
</li>
|
||||
|
|
@ -15,20 +15,32 @@
|
|||
{% trans "Editing" as editing_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=document.title icon="doc-full-inverse" usage_object=document %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<form action="{% url 'wagtaildocs_edit_document' document.id %}" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<ul class="fields">
|
||||
{% for field in form %}
|
||||
{% if field.name == 'file' %}
|
||||
{% include "wagtaildocs/documents/_file_field.html" %}
|
||||
{% else %}
|
||||
{% include "wagtailadmin/shared/field_as_li.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<li><input type="submit" value="{% trans 'Save' %}" /> <a href="{% url 'wagtaildocs_delete_document' document.id %}" class="button button-secondary no">{% trans "Delete document" %}</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
<div class="row row-flush nice-padding">
|
||||
|
||||
<div class="col10 divider-after">
|
||||
<form action="{% url 'wagtaildocs_edit_document' document.id %}" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<ul class="fields">
|
||||
{% for field in form %}
|
||||
{% if field.name == 'file' %}
|
||||
{% include "wagtaildocs/documents/_file_field_as_li.html" %}
|
||||
{% else %}
|
||||
{% include "wagtailadmin/shared/field_as_li.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<li><input type="submit" value="{% trans 'Save' %}" /> <a href="{% url 'wagtaildocs_delete_document' document.id %}" class="button button-secondary no">{% trans "Delete document" %}</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<dl>
|
||||
{% if document.file %}
|
||||
<dt>{% trans "Filesize" %}</dt>
|
||||
<dd>{{ document.file.size|filesizeformat }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import re
|
|||
from six import BytesIO, text_type
|
||||
|
||||
from taggit.managers import TaggableManager
|
||||
from willow.image import Image as WillowImage
|
||||
|
||||
from django.core.files import File
|
||||
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
|
||||
|
|
@ -80,6 +81,19 @@ class AbstractImage(models.Model, TagSearchable):
|
|||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_willow_image(self):
|
||||
try:
|
||||
image_file = self.file.file # triggers a call to self.storage.open, so IOErrors from missing files will be raised at this point
|
||||
except IOError as e:
|
||||
# re-throw this as a SourceImageIOError so that calling code can distinguish
|
||||
# these from IOErrors elsewhere in the process
|
||||
raise SourceImageIOError(text_type(e))
|
||||
|
||||
image_file.open('rb')
|
||||
image_file.seek(0)
|
||||
|
||||
return WillowImage.open(image_file)
|
||||
|
||||
def get_rect(self):
|
||||
return Rect(0, 0, self.width, self.height)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{% extends "wagtailadmin/shared/field_as_li.html" %}
|
||||
{% load i18n %}
|
||||
{% extends "wagtailadmin/shared/field.html" %}
|
||||
{% load i18n wagtailimages_tags %}
|
||||
{% block form_field %}
|
||||
<span class="icon icon-image">{{ image.filename }}</span><br /><br />
|
||||
{% image image original as original_image %}
|
||||
|
||||
{% trans "Change image:" %}
|
||||
<a href="{{ original_image.url }}" class="icon icon-image">{{ image.filename }}</a> ({{ original_image.width }}x{{ original_image.height}})<br /><br />
|
||||
|
||||
{% trans "Change image file:" %}
|
||||
{{ field }}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
<li class="{% if field.field.required %}required{% endif %} {{ wrapper_classes }} {{ li_classes }} {% if field.errors %}error{% endif %}">
|
||||
{% include "wagtailimages/images/_file_field.html" %}
|
||||
</li>
|
||||
|
|
@ -28,14 +28,14 @@
|
|||
|
||||
<div class="row row-flush nice-padding">
|
||||
|
||||
<div class="col7">
|
||||
<div class="col5">
|
||||
<form action="{% url 'wagtailimages_edit_image' image.id %}" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<ul class="fields">
|
||||
{% for field in form %}
|
||||
|
||||
{% if field.name == 'file' %}
|
||||
{% include "wagtailimages/images/_file_field.html" %}
|
||||
{% include "wagtailimages/images/_file_field_as_li.html" %}
|
||||
{% elif field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<div class="col5 divider-after">
|
||||
<h2 class="label">{% trans "Focal point (optional)" %}</h2>
|
||||
<p>{% trans "To define this image's most important region, drag a box over the image below." %} {% if image.focal_point %}({% trans "Current focal point shown" %}){% endif %}</p>
|
||||
|
||||
|
|
@ -64,10 +64,22 @@
|
|||
|
||||
<div class="current-focal-point-indicator{% if not image.focal_point %} hidden{% endif %}"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col2 ">
|
||||
{% if url_generator_enabled %}
|
||||
<a href="{% url 'wagtailimages_url_generator' image.id %}" class="button bicolor icon icon-link">{% trans "URL Generator" %}</a>
|
||||
<hr />
|
||||
{% endif %}
|
||||
|
||||
{% image image original as original_image %}
|
||||
|
||||
<dl>
|
||||
<dt>{% trans "Max dimensions" %}</dt>
|
||||
<dd>{{ original_image.width }}x{{ original_image.height }}</dd>
|
||||
<dt>{% trans "Filesize" %}</dt>
|
||||
<dd>{{ image.file.size|filesizeformat }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import unittest
|
||||
from willow.image import Image as WillowImage
|
||||
|
||||
from django.test import TestCase
|
||||
from django.core.urlresolvers import reverse
|
||||
|
|
@ -13,7 +14,7 @@ from django.db import connection
|
|||
from wagtail.tests.utils import WagtailTestUtils, test_concurrently
|
||||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.tests.models import EventPage, EventPageCarouselItem
|
||||
from wagtail.wagtailimages.models import Rendition, Filter
|
||||
from wagtail.wagtailimages.models import Rendition, Filter, SourceImageIOError
|
||||
from wagtail.wagtailimages.backends import get_image_backend
|
||||
from wagtail.wagtailimages.backends.pillow import PillowBackend
|
||||
from wagtail.wagtailimages.rect import Rect
|
||||
|
|
@ -268,6 +269,29 @@ class TestGetUsage(TestCase):
|
|||
self.assertTrue(issubclass(Page, type(self.image.get_usage()[0])))
|
||||
|
||||
|
||||
class TestGetWillowImage(TestCase):
|
||||
fixtures = ['test.json']
|
||||
|
||||
def setUp(self):
|
||||
self.image = Image.objects.create(
|
||||
title="Test image",
|
||||
file=get_test_image_file(),
|
||||
)
|
||||
|
||||
def test_willow_image_object_returned(self):
|
||||
willow_image = self.image.get_willow_image()
|
||||
|
||||
self.assertIsInstance(willow_image, WillowImage)
|
||||
|
||||
def test_with_missing_image(self):
|
||||
# Image id=1 in test fixtures has a missing image file
|
||||
bad_image = Image.objects.get(id=1)
|
||||
|
||||
# Attempting to get the Willow image for images without files
|
||||
# should raise a SourceImageIOError
|
||||
self.assertRaises(SourceImageIOError, bad_image.get_willow_image)
|
||||
|
||||
|
||||
class TestIssue573(TestCase):
|
||||
"""
|
||||
This tests for a bug which causes filename limit on Renditions to be reached
|
||||
|
|
|
|||
Loading…
Reference in a new issue