kopia lustrzana https://github.com/wagtail/wagtail
Merge branch '146-display-calculated-usage'
Conflicts: wagtail/wagtailimages/models.py wagtail/wagtailimages/templates/wagtailimages/images/edit.html wagtail/wagtailimages/tests.py wagtail/wagtailimages/urls.py wagtail/wagtailimages/views/images.pypull/540/head
commit
1ac807ce09
|
@ -562,6 +562,14 @@
|
|||
"submit_time": "2014-01-01T12:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "tests.AdvertPlacement",
|
||||
"fields": {
|
||||
"page": 2,
|
||||
"advert": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "tests.advert",
|
||||
|
@ -578,17 +586,6 @@
|
|||
"created_at": "2014-01-01T12:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "wagtailimages.Image",
|
||||
"fields": {
|
||||
"title": "test image",
|
||||
"created_at": "2014-01-01T12:00:00.000Z",
|
||||
"width": 0,
|
||||
"height": 0
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "wagtailcore.pageviewrestriction",
|
||||
|
|
|
@ -325,9 +325,11 @@ FormPage.content_panels = [
|
|||
]
|
||||
|
||||
|
||||
# Snippets
|
||||
|
||||
# Snippets
|
||||
class AdvertPlacement(models.Model):
|
||||
page = ParentalKey('wagtailcore.Page', related_name='advert_placements')
|
||||
advert = models.ForeignKey('tests.Advert', related_name='+')
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Advert(models.Model):
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
<header class="nice-padding {% if merged %}merged{% endif %} {% if tabbed %}tab-merged{% endif %} {% if search_form %}hasform{% endif %}">
|
||||
<div class="row">
|
||||
<div class="left">
|
||||
|
@ -16,6 +17,12 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<div class="right">
|
||||
{% usage_count_enabled as uc_enabled %}
|
||||
{% if uc_enabled and usage_object %}
|
||||
<div class="usagecount">
|
||||
<a href="{{ usage_object.usage_url }}">{% blocktrans count useage_count=usage_object.get_usage.count %}Used {{ useage_count }} time{% plural %}Used {{ useage_count }} times{% endblocktrans %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if add_link %}
|
||||
<div class="addbutton">
|
||||
<a href="{% url add_link %}" class="button bicolor icon icon-plus">{{ add_text }}</a>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django import template
|
||||
from django.core import urlresolvers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -121,3 +122,13 @@ def hook_output(hook_name):
|
|||
"""
|
||||
snippets = [fn() for fn in hooks.get_hooks(hook_name)]
|
||||
return ''.join(snippets)
|
||||
|
||||
|
||||
@register.assignment_tag
|
||||
def usage_count_enabled():
|
||||
if hasattr(
|
||||
settings, 'WAGTAIL_USAGE_COUNT_ENABLED'
|
||||
) and settings.WAGTAIL_USAGE_COUNT_ENABLED:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from django.test import TestCase
|
||||
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 django.core.urlresolvers import reverse
|
||||
from django.core import mail
|
||||
|
||||
|
||||
class TestHome(TestCase, WagtailTestUtils):
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
from modelcluster.fields import ParentalKey
|
||||
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
def get_object_usage(obj):
|
||||
"Returns a queryset of pages that link to a particular object"
|
||||
|
||||
pages = Page.objects.none()
|
||||
|
||||
# get all the relation objects for obj
|
||||
relations = type(obj)._meta.get_all_related_objects(
|
||||
include_hidden=True,
|
||||
include_proxy_eq=True
|
||||
)
|
||||
for relation in relations:
|
||||
# if the relation is between obj and a page, get the page
|
||||
if issubclass(relation.model, Page):
|
||||
pages |= Page.objects.filter(
|
||||
id__in=relation.model._base_manager.filter(**{
|
||||
relation.field.name: obj.id
|
||||
}).values_list('id', flat=True)
|
||||
)
|
||||
else:
|
||||
# if the relation is between obj and an object that has a page as a
|
||||
# property, return the page
|
||||
for f in relation.model._meta.fields:
|
||||
if isinstance(f, ParentalKey) and issubclass(f.rel.to, Page):
|
||||
pages |= Page.objects.filter(
|
||||
id__in=relation.model._base_manager.filter(
|
||||
**{
|
||||
relation.field.name: obj.id
|
||||
}).values_list(f.attname, flat=True)
|
||||
)
|
||||
|
||||
return pages
|
|
@ -11,4 +11,5 @@ urlpatterns = [
|
|||
url(r'^chooser/$', chooser.chooser, name='wagtaildocs_chooser'),
|
||||
url(r'^chooser/(\d+)/$', chooser.document_chosen, name='wagtaildocs_document_chosen'),
|
||||
url(r'^chooser/upload/$', chooser.chooser_upload, name='wagtaildocs_chooser_upload'),
|
||||
url(r'^usage/(\d+)/$', documents.usage, name='wagtaildocs_document_usage'),
|
||||
]
|
||||
|
|
|
@ -12,6 +12,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
from wagtail.wagtailadmin.taggable import TagSearchable
|
||||
from wagtail.wagtailadmin.utils import get_object_usage
|
||||
from wagtail.wagtailsearch import indexed
|
||||
|
||||
|
||||
|
@ -47,6 +48,14 @@ class Document(models.Model, TagSearchable):
|
|||
def url(self):
|
||||
return reverse('wagtaildocs_serve', args=[self.id, self.filename])
|
||||
|
||||
def get_usage(self):
|
||||
return get_object_usage(self)
|
||||
|
||||
@property
|
||||
def usage_url(self):
|
||||
return reverse('wagtaildocs_document_usage',
|
||||
args=(self.id,))
|
||||
|
||||
def is_editable_by_user(self, user):
|
||||
if user.has_perm('wagtaildocs.change_document'):
|
||||
# user has global permission to change documents
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
{% block content %}
|
||||
{% trans "Editing" as editing_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=document.title icon="doc-full-inverse" %}
|
||||
{% 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">
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "wagtailadmin/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titletag %}{% blocktrans with title=document.title %}Usage of {{ title }}{% endblocktrans %}{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "Usage of" as usage_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=usage_str subtitle=document.title %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<table class="listing">
|
||||
<col />
|
||||
<col width="30%"/>
|
||||
<col width="15%"/>
|
||||
<col width="15%"/>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title">{% trans "Title" %}</th>
|
||||
<th>{% trans "Parent" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for page in used_by %}
|
||||
<tr>
|
||||
<td class="title" valign="top">
|
||||
<h2><a href="{% url 'wagtailadmin_pages_edit' page.id %}" title="{% trans 'Edit this page' %}">{{ page.title }}</a></h2>
|
||||
</td>
|
||||
<td>
|
||||
{% if page.get_parent %}
|
||||
<a href="{% url 'wagtailadmin_explore' page.get_parent.id %}">{{ page.get_parent.title }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ page.content_type.model_class.get_verbose_name }}
|
||||
</td>
|
||||
<td>
|
||||
{% if page.live %}
|
||||
<a href="{{ page.url }}" target="_blank" class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</a>
|
||||
{% else %}
|
||||
<span class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "wagtailadmin/shared/pagination_nav.html" with items=used_by linkurl="-" %}
|
||||
{% endblock %}
|
|
@ -5,8 +5,13 @@ from django.contrib.auth import get_user_model
|
|||
from django.contrib.auth.models import Group, Permission
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.files.base import ContentFile
|
||||
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.wagtaildocs.models import Document
|
||||
|
||||
from wagtail.wagtaildocs import models
|
||||
|
||||
|
@ -316,3 +321,99 @@ class TestDocumentFilenameProperties(TestCase):
|
|||
def tearDown(self):
|
||||
self.document.delete()
|
||||
self.extensionless_document.delete()
|
||||
|
||||
|
||||
class TestUsageCount(TestCase, WagtailTestUtils):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
def setUp(self):
|
||||
self.login()
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_unused_document_usage_count(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
self.assertEqual(doc.get_usage().count(), 0)
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_used_document_usage_count(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_related_link = EventPageRelatedLink()
|
||||
event_page_related_link.page = page
|
||||
event_page_related_link.link_document = doc
|
||||
event_page_related_link.save()
|
||||
self.assertEqual(doc.get_usage().count(), 1)
|
||||
|
||||
def test_usage_count_does_not_appear(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_related_link = EventPageRelatedLink()
|
||||
event_page_related_link.page = page
|
||||
event_page_related_link.link_document = doc
|
||||
event_page_related_link.save()
|
||||
response = self.client.get(reverse('wagtaildocs_edit_document',
|
||||
args=(1,)))
|
||||
self.assertNotContains(response, 'Used 1 time')
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_usage_count_appears(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_related_link = EventPageRelatedLink()
|
||||
event_page_related_link.page = page
|
||||
event_page_related_link.link_document = doc
|
||||
event_page_related_link.save()
|
||||
response = self.client.get(reverse('wagtaildocs_edit_document',
|
||||
args=(1,)))
|
||||
self.assertContains(response, 'Used 1 time')
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_usage_count_zero_appears(self):
|
||||
response = self.client.get(reverse('wagtaildocs_edit_document',
|
||||
args=(1,)))
|
||||
self.assertContains(response, 'Used 0 times')
|
||||
|
||||
|
||||
class TestGetUsage(TestCase, WagtailTestUtils):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
def setUp(self):
|
||||
self.login()
|
||||
|
||||
def test_document_get_usage_not_enabled(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
self.assertEqual(list(doc.get_usage()), [])
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_unused_document_get_usage(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
self.assertEqual(list(doc.get_usage()), [])
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_used_document_get_usage(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_related_link = EventPageRelatedLink()
|
||||
event_page_related_link.page = page
|
||||
event_page_related_link.link_document = doc
|
||||
event_page_related_link.save()
|
||||
self.assertTrue(issubclass(Page, type(doc.get_usage()[0])))
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_usage_page(self):
|
||||
doc = Document.objects.get(id=1)
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_related_link = EventPageRelatedLink()
|
||||
event_page_related_link.page = page
|
||||
event_page_related_link.link_document = doc
|
||||
event_page_related_link.save()
|
||||
response = self.client.get(reverse('wagtaildocs_document_usage',
|
||||
args=(1,)))
|
||||
self.assertContains(response, 'Christmas')
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_usage_page_no_usage(self):
|
||||
response = self.client.get(reverse('wagtaildocs_document_usage',
|
||||
args=(1,)))
|
||||
# There's no usage so there should be no table rows
|
||||
self.assertRegex(response.content, b'<tbody>(\s|\n)*</tbody>')
|
||||
|
|
|
@ -5,6 +5,7 @@ from django.contrib.auth.decorators import permission_required
|
|||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.vary import vary_on_headers
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from wagtail.wagtailadmin.forms import SearchForm
|
||||
|
||||
|
@ -120,7 +121,7 @@ def edit(request, document_id):
|
|||
|
||||
return render(request, "wagtaildocs/documents/edit.html", {
|
||||
'document': doc,
|
||||
'form': form,
|
||||
'form': form
|
||||
})
|
||||
|
||||
|
||||
|
@ -139,3 +140,24 @@ def delete(request, document_id):
|
|||
return render(request, "wagtaildocs/documents/confirm_delete.html", {
|
||||
'document': doc,
|
||||
})
|
||||
|
||||
|
||||
@permission_required('wagtailadmin.access_admin')
|
||||
def usage(request, document_id):
|
||||
doc = get_object_or_404(Document, id=document_id)
|
||||
|
||||
# Pagination
|
||||
p = request.GET.get('p', 1)
|
||||
paginator = Paginator(doc.get_usage(), 20)
|
||||
|
||||
try:
|
||||
used_by = paginator.page(p)
|
||||
except PageNotAnInteger:
|
||||
used_by = paginator.page(1)
|
||||
except EmptyPage:
|
||||
used_by = paginator.page(paginator.num_pages)
|
||||
|
||||
return render(request, "wagtaildocs/documents/usage.html", {
|
||||
'document': doc,
|
||||
'used_by': used_by
|
||||
})
|
||||
|
|
|
@ -10,6 +10,7 @@ urlpatterns = [
|
|||
url(r'^(\d+)/generate_url/$', images.url_generator, name='wagtailimages_url_generator'),
|
||||
url(r'^(\d+)/generate_url/(.*)/$', images.generate_url, name='wagtailimages_generate_url'),
|
||||
url(r'^add/$', images.add, name='wagtailimages_add_image'),
|
||||
url(r'^usage/(\d+)/$', images.usage, name='wagtailimages_image_usage'),
|
||||
|
||||
url(r'^multiple/add/$', multiple.add, name='wagtailimages_add_multiple'),
|
||||
url(r'^multiple/(\d+)/$', multiple.edit, name='wagtailimages_edit_multiple'),
|
||||
|
|
|
@ -16,6 +16,7 @@ from django.conf import settings
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.functional import cached_property
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from unidecode import unidecode
|
||||
|
||||
|
@ -25,6 +26,7 @@ from wagtail.wagtailsearch import indexed
|
|||
from wagtail.wagtailimages.utils.validators import validate_image_format
|
||||
from wagtail.wagtailimages.utils.focal_point import FocalPoint
|
||||
from wagtail.wagtailimages.utils.feature_detection import FeatureDetector, opencv_available
|
||||
from wagtail.wagtailadmin.utils import get_object_usage
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
|
@ -57,6 +59,14 @@ class AbstractImage(models.Model, TagSearchable):
|
|||
focal_point_width = models.PositiveIntegerField(null=True, editable=False)
|
||||
focal_point_height = models.PositiveIntegerField(null=True, editable=False)
|
||||
|
||||
def get_usage(self):
|
||||
return get_object_usage(self)
|
||||
|
||||
@property
|
||||
def usage_url(self):
|
||||
return reverse('wagtailimages_image_usage',
|
||||
args=(self.id,))
|
||||
|
||||
search_fields = TagSearchable.search_fields + (
|
||||
indexed.FilterField('uploaded_by_user'),
|
||||
)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
{% block content %}
|
||||
{% trans "Editing" as editing_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=image.title icon="image" %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=image.title icon="image" usage_object=image %}
|
||||
|
||||
<div class="row row-flush nice-padding">
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "wagtailadmin/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titletag %}{% blocktrans with title=image.title %}Usage of {{ title }}{% endblocktrans %}{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "Usage of" as usage_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=usage_str subtitle=image.title %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<table class="listing">
|
||||
<col />
|
||||
<col width="30%"/>
|
||||
<col width="15%"/>
|
||||
<col width="15%"/>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title">{% trans "Title" %}</th>
|
||||
<th>{% trans "Parent" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for page in used_by %}
|
||||
<tr>
|
||||
<td class="title" valign="top">
|
||||
<h2><a href="{% url 'wagtailadmin_pages_edit' page.id %}" title="{% trans 'Edit this page' %}">{{ page.title }}</a></h2>
|
||||
</td>
|
||||
<td>
|
||||
{% if page.get_parent %}
|
||||
<a href="{% url 'wagtailadmin_explore' page.get_parent.id %}">{{ page.get_parent.title }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ page.content_type.model_class.get_verbose_name }}
|
||||
</td>
|
||||
<td>
|
||||
{% if page.live %}
|
||||
<a href="{{ page.url }}" target="_blank" class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</a>
|
||||
{% else %}
|
||||
<span class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "wagtailadmin/shared/pagination_nav.html" with items=used_by linkurl="-" %}
|
||||
{% endblock %}
|
|
@ -8,6 +8,7 @@ from django.utils import six
|
|||
from django.utils.http import urlquote
|
||||
from django.utils import timezone
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django import template
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
|
@ -27,6 +28,8 @@ from wagtail.wagtailimages.backends.pillow import PillowBackend
|
|||
from wagtail.wagtailimages.utils.crop import crop_to_point, CropBox
|
||||
from wagtail.wagtailimages.utils.focal_point import FocalPoint
|
||||
from wagtail.wagtailimages.utils.crypto import generate_signature, verify_signature
|
||||
from wagtail.tests.models import EventPage, EventPageCarouselItem
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
def get_test_image_file():
|
||||
|
@ -484,6 +487,55 @@ class TestFormat(TestCase):
|
|||
self.assertEqual(result, self.format)
|
||||
|
||||
|
||||
class TestUsageCount(TestCase):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
def setUp(self):
|
||||
self.image = Image.objects.create(
|
||||
title="Test image",
|
||||
file=get_test_image_file(),
|
||||
)
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_unused_image_usage_count(self):
|
||||
self.assertEqual(self.image.get_usage().count(), 0)
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_used_image_document_usage_count(self):
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_carousel_item = EventPageCarouselItem()
|
||||
event_page_carousel_item.page = page
|
||||
event_page_carousel_item.image = self.image
|
||||
event_page_carousel_item.save()
|
||||
self.assertEqual(self.image.get_usage().count(), 1)
|
||||
|
||||
|
||||
class TestGetUsage(TestCase):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
def setUp(self):
|
||||
self.image = Image.objects.create(
|
||||
title="Test image",
|
||||
file=get_test_image_file(),
|
||||
)
|
||||
|
||||
def test_image_get_usage_not_enabled(self):
|
||||
self.assertEqual(list(self.image.get_usage()), [])
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_unused_image_get_usage(self):
|
||||
self.assertEqual(list(self.image.get_usage()), [])
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_used_image_document_get_usage(self):
|
||||
page = EventPage.objects.get(id=4)
|
||||
event_page_carousel_item = EventPageCarouselItem()
|
||||
event_page_carousel_item.page = page
|
||||
event_page_carousel_item.image = self.image
|
||||
event_page_carousel_item.save()
|
||||
self.assertTrue(issubclass(Page, type(self.image.get_usage()[0])))
|
||||
|
||||
|
||||
class TestMultipleImageUploader(TestCase, WagtailTestUtils):
|
||||
"""
|
||||
This tests the multiple image upload views located in wagtailimages/views/multiple.py
|
||||
|
|
|
@ -38,7 +38,6 @@ def index(request):
|
|||
if form.is_valid():
|
||||
query_string = form.cleaned_data['q']
|
||||
|
||||
is_searching = True
|
||||
if not request.user.has_perm('wagtailimages.change_image'):
|
||||
# restrict to the user's own images
|
||||
images = Image.search(query_string, filters={'uploaded_by_user_id': request.user.id})
|
||||
|
@ -214,3 +213,24 @@ def add(request):
|
|||
return render(request, "wagtailimages/images/add.html", {
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
||||
@permission_required('wagtailadmin.access_admin')
|
||||
def usage(request, image_id):
|
||||
image = get_object_or_404(get_image_model(), id=image_id)
|
||||
|
||||
# Pagination
|
||||
p = request.GET.get('p', 1)
|
||||
paginator = Paginator(image.get_usage(), 20)
|
||||
|
||||
try:
|
||||
used_by = paginator.page(p)
|
||||
except PageNotAnInteger:
|
||||
used_by = paginator.page(1)
|
||||
except EmptyPage:
|
||||
used_by = paginator.page(paginator.num_pages)
|
||||
|
||||
return render(request, "wagtailimages/images/usage.html", {
|
||||
'image': image,
|
||||
'used_by': used_by
|
||||
})
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from wagtail.wagtailadmin.utils import get_object_usage
|
||||
|
||||
SNIPPET_MODELS = []
|
||||
|
||||
|
@ -18,5 +21,15 @@ def get_snippet_content_types():
|
|||
|
||||
def register_snippet(model):
|
||||
if model not in SNIPPET_MODELS:
|
||||
model.get_usage = get_object_usage
|
||||
model.usage_url = get_snippet_usage_url
|
||||
SNIPPET_MODELS.append(model)
|
||||
SNIPPET_MODELS.sort(key=lambda x: x._meta.verbose_name)
|
||||
|
||||
|
||||
def get_snippet_usage_url(self):
|
||||
content_type = ContentType.objects.get_for_model(self)
|
||||
return reverse('wagtailsnippets_usage',
|
||||
args=(content_type.app_label,
|
||||
content_type.model,
|
||||
self.id,))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% block bodyclass %}menu-snippets{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "Editing" as editing_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=instance icon="snippet" %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=instance icon="snippet" usage_object=instance %}
|
||||
|
||||
<form action="{% url 'wagtailsnippets_edit' content_type.app_label content_type.model instance.id %}" method="POST">
|
||||
{% csrf_token %}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "wagtailadmin/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titletag %}{% blocktrans with title=instance %}Usage of {{ title }}{% endblocktrans %}{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "Usage of" as usage_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=usage_str subtitle=instance %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<table class="listing">
|
||||
<col />
|
||||
<col width="30%"/>
|
||||
<col width="15%"/>
|
||||
<col width="15%"/>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title">{% trans "Title" %}</th>
|
||||
<th>{% trans "Parent" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for page in used_by %}
|
||||
<tr>
|
||||
<td class="title" valign="top">
|
||||
<h2><a href="{% url 'wagtailadmin_pages_edit' page.id %}" title="{% trans 'Edit this page' %}">{{ page.title }}</a></h2>
|
||||
</td>
|
||||
<td>
|
||||
{% if page.get_parent %}
|
||||
<a href="{% url 'wagtailadmin_explore' page.get_parent.id %}">{{ page.get_parent.title }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ page.content_type.model_class.get_verbose_name }}
|
||||
</td>
|
||||
<td>
|
||||
{% if page.live %}
|
||||
<a href="{{ page.url }}" target="_blank" class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</a>
|
||||
{% else %}
|
||||
<span class="status-tag {% if page.status_string != "draft" %}primary{% endif %}">{{ page.status_string }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "wagtailadmin/shared/pagination_nav.html" with items=used_by linkurl="-"%}
|
||||
{% endblock %}
|
|
@ -2,6 +2,7 @@ from django.test import TestCase
|
|||
from django.core.urlresolvers import reverse
|
||||
|
||||
from wagtail.tests.utils import WagtailTestUtils
|
||||
from django.test.utils import override_settings
|
||||
from wagtail.tests.models import Advert, AlphaSnippet, ZuluSnippet
|
||||
from wagtail.wagtailsnippets.models import register_snippet, SNIPPET_MODELS
|
||||
|
||||
|
@ -9,6 +10,7 @@ from wagtail.wagtailsnippets.views.snippets import (
|
|||
get_snippet_edit_handler
|
||||
)
|
||||
from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
class TestSnippetIndexView(TestCase, WagtailTestUtils):
|
||||
|
@ -185,3 +187,21 @@ class TestSnippetOrdering(TestCase):
|
|||
# may get registered elsewhere during test
|
||||
self.assertLess(SNIPPET_MODELS.index(AlphaSnippet),
|
||||
SNIPPET_MODELS.index(ZuluSnippet))
|
||||
|
||||
|
||||
class TestUsageCount(TestCase):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_snippet_usage_count(self):
|
||||
advert = Advert.objects.get(id=1)
|
||||
self.assertEqual(advert.get_usage().count(), 1)
|
||||
|
||||
|
||||
class TestUsedBy(TestCase):
|
||||
fixtures = ['wagtail/tests/fixtures/test.json']
|
||||
|
||||
@override_settings(WAGTAIL_USAGE_COUNT_ENABLED=True)
|
||||
def test_snippet_used_by(self):
|
||||
advert = Advert.objects.get(id=1)
|
||||
self.assertEqual(type(advert.get_usage()[0]), Page)
|
||||
|
|
|
@ -13,4 +13,5 @@ urlpatterns = [
|
|||
url(r'^(\w+)/(\w+)/new/$', snippets.create, name='wagtailsnippets_create'),
|
||||
url(r'^(\w+)/(\w+)/(\d+)/$', snippets.edit, name='wagtailsnippets_edit'),
|
||||
url(r'^(\w+)/(\w+)/(\d+)/delete/$', snippets.delete, name='wagtailsnippets_delete'),
|
||||
url(r'^(\w+)/(\w+)/(\d+)/usage/$', snippets.usage, name='wagtailsnippets_usage'),
|
||||
]
|
||||
|
|
|
@ -7,6 +7,8 @@ from django.contrib import messages
|
|||
from django.contrib.auth.decorators import permission_required
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
|
||||
from wagtail.wagtailadmin.edit_handlers import ObjectList, extract_panel_definitions_from_model_class
|
||||
|
||||
|
@ -182,7 +184,7 @@ def edit(request, content_type_app_name, content_type_model_name, id):
|
|||
'content_type': content_type,
|
||||
'snippet_type_name': snippet_type_name,
|
||||
'instance': instance,
|
||||
'edit_handler': edit_handler,
|
||||
'edit_handler': edit_handler
|
||||
})
|
||||
|
||||
|
||||
|
@ -213,3 +215,26 @@ def delete(request, content_type_app_name, content_type_model_name, id):
|
|||
'snippet_type_name': snippet_type_name,
|
||||
'instance': instance,
|
||||
})
|
||||
|
||||
|
||||
@permission_required('wagtailadmin.access_admin')
|
||||
def usage(request, content_type_app_name, content_type_model_name, id):
|
||||
content_type = get_content_type_from_url_params(content_type_app_name, content_type_model_name)
|
||||
model = content_type.model_class()
|
||||
instance = get_object_or_404(model, id=id)
|
||||
|
||||
# Pagination
|
||||
p = request.GET.get('p', 1)
|
||||
paginator = Paginator(instance.get_usage(), 20)
|
||||
|
||||
try:
|
||||
used_by = paginator.page(p)
|
||||
except PageNotAnInteger:
|
||||
used_by = paginator.page(1)
|
||||
except EmptyPage:
|
||||
used_by = paginator.page(paginator.num_pages)
|
||||
|
||||
return render(request, "wagtailsnippets/snippets/usage.html", {
|
||||
'instance': instance,
|
||||
'used_by': used_by
|
||||
})
|
||||
|
|
Ładowanie…
Reference in New Issue