Add usage counters for images, documents and snippets

This commit is contained in:
Tom Talbot 2014-07-07 17:20:41 +01:00
parent 26cacbc95a
commit 94e0f74024
17 changed files with 173 additions and 9 deletions

View file

@ -16,6 +16,11 @@
{% endif %}
</div>
<div class="right">
{% if usage_count or usage_count == 0 %}
<div class="usagecount">
<a href="{{ usage_url }}">Used {{ usage_count }} Time{% if not usage_count == 1 %}s{% endif %}</a>
</div>
{% endif %}
{% if add_link %}
<div class="addbutton">
<a href="{% url add_link %}" class="button bicolor icon icon-plus">{{ add_text }}</a>
@ -23,4 +28,4 @@
{% endif %}
</div>
</div>
</header>
</header>

View file

@ -0,0 +1,36 @@
from wagtail.wagtailcore.models import Page
def usage_count(self):
"""The number of times that an selfect has been used"""
count = 0
relations = self._meta.get_all_related_objects(
include_hidden=True,
include_proxy_eq=True
)
for relation in relations:
count += relation.model._base_manager.filter(
**{relation.field.name: self.id}
).count()
return count
def used_by(self):
related_objects = []
result = []
relations = self._meta.get_all_related_objects(
include_hidden=True,
include_proxy_eq=True
)
for relation in relations:
related_objects.extend(list(relation.model._base_manager.filter(
**{relation.field.name: self.id}
)))
for r in related_objects:
if isinstance(r, Page):
result.append(r)
elif hasattr(r, 'page'):
result.append(r.page)
return result

View file

@ -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'),
]

View file

@ -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 usage_count, used_by
@python_2_unicode_compatible
@ -51,6 +52,14 @@ class Document(models.Model, TagSearchable):
def url(self):
return reverse('wagtaildocs_serve', args=[self.id, self.filename])
@property
def usage_count(self):
return usage_count(self)
@property
def used_by(self):
return used_by(self)
def is_editable_by_user(self, user):
if user.has_perm('wagtaildocs.change_document'):
# user has global permission to change documents

View file

@ -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_count=document.usage_count usage_url=usage_url %}
<div class="nice-padding">
<form action="{% url 'wagtaildocs_edit_document' document.id %}" method="POST" enctype="multipart/form-data">
@ -30,6 +30,6 @@
</ul>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,17 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with title=document.title %}{{ title }} Usage{% endblocktrans %}{% endblock %}
{% block content %}
{% include "wagtailadmin/shared/header.html" with title="Usage" %}
<div class="nice-padding">
<ul class="listing">
{% for u in document.used_by %}
<li>
<a href="{{ u.url }}">{{ u.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View file

@ -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
@ -101,6 +102,9 @@ def edit(request, document_id):
if not doc.is_editable_by_user(request.user):
raise PermissionDenied
usage_url = reverse('wagtaildocs_document_usage',
args=(doc.id,))
if request.POST:
original_file = doc.file
form = DocumentForm(request.POST, request.FILES, instance=doc)
@ -121,6 +125,7 @@ def edit(request, document_id):
return render(request, "wagtaildocs/documents/edit.html", {
'document': doc,
'form': form,
'usage_url': usage_url
})
@ -139,3 +144,12 @@ 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)
return render(request, "wagtaildocs/documents/usage.html", {
'document': doc,
})

View file

@ -21,6 +21,7 @@ from unidecode import unidecode
from wagtail.wagtailadmin.taggable import TagSearchable
from wagtail.wagtailimages.backends import get_image_backend
from .utils import validate_image_format
from wagtail.wagtailadmin.utils import usage_count, used_by
@python_2_unicode_compatible
@ -48,6 +49,14 @@ class AbstractImage(models.Model, TagSearchable):
tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))
@property
def usage_count(self):
return usage_count(self)
@property
def used_by(self):
return used_by(self)
indexed_fields = {
'uploaded_by_user_id': {
'type': 'integer',

View file

@ -13,10 +13,10 @@
{% 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_count=image.usage_count usage_url=usage_url %}
<div class="row row-flush nice-padding">
<div class="col7">
<form action="{% url 'wagtailimages_edit_image' image.id %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
@ -33,7 +33,7 @@
<li><input type="submit" value="{% trans 'Save' %}" /><a href="{% url 'wagtailimages_delete_image' image.id %}" class="button button-secondary no">{% trans "Delete image" %}</a></li>
</ul>
</form>
</div>
<div class="col5">
{% image image max-800x600 %}

View file

@ -0,0 +1,17 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with title=document.title %}{{ title }} Usage{% endblocktrans %}{% endblock %}
{% block content %}
{% include "wagtailadmin/shared/header.html" with title="Usage" %}
<div class="nice-padding">
<ul class="listing">
{% for u in image.used_by %}
<li>
<a href="{{ u.url }}">{{ u.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View file

@ -6,6 +6,7 @@ urlpatterns = [
url(r'^(\d+)/$', images.edit, name='wagtailimages_edit_image'),
url(r'^(\d+)/delete/$', images.delete, name='wagtailimages_delete_image'),
url(r'^add/$', images.add, name='wagtailimages_add_image'),
url(r'^usage/(\d+)/$', images.usage, name='wagtailimages_image_usage'),
url(r'^chooser/$', chooser.chooser, name='wagtailimages_chooser'),
url(r'^chooser/(\d+)/$', chooser.image_chosen, name='wagtailimages_image_chosen'),

View file

@ -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
@ -80,6 +81,9 @@ def edit(request, image_id):
if not image.is_editable_by_user(request.user):
raise PermissionDenied
usage_url = reverse('wagtailimages_image_usage',
args=(image.id,))
if request.POST:
original_file = image.file
form = ImageForm(request.POST, request.FILES, instance=image)
@ -101,6 +105,7 @@ def edit(request, image_id):
return render(request, "wagtailimages/images/edit.html", {
'image': image,
'form': form,
'usage_url': usage_url
})
@ -141,3 +146,14 @@ 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)
print dir(image)
return render(request, "wagtailimages/images/usage.html", {
'image': image,
})

View file

@ -1,4 +1,5 @@
from django.contrib.contenttypes.models import ContentType
from wagtail.wagtailadmin.utils import usage_count, used_by
SNIPPET_MODELS = []
@ -18,5 +19,7 @@ def get_snippet_content_types():
def register_snippet(model):
if model not in SNIPPET_MODELS:
model.usage_count = usage_count
model.used_by = used_by
SNIPPET_MODELS.append(model)
SNIPPET_MODELS.sort(key=lambda x: x._meta.verbose_name)

View file

@ -4,12 +4,12 @@
{% 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_count=instance.usage_count usage_url=usage_url %}
<form action="{% url 'wagtailsnippets_edit' content_type.app_label content_type.model instance.id %}" method="POST">
{% csrf_token %}
{{ edit_handler.render_form_content }}
<footer>
<ul>
<li class="actions">

View file

@ -0,0 +1,17 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with title=document.title %}{{ title }} Usage{% endblocktrans %}{% endblock %}
{% block content %}
{% include "wagtailadmin/shared/header.html" with title="Usage" %}
<div class="nice-padding">
<ul class="listing">
{% for u in document.used_by %}
<li>
<a href="{{ u.url }}">{{ u.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View file

@ -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'),
]

View file

@ -7,6 +7,7 @@ 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 wagtail.wagtailadmin.edit_handlers import ObjectList, extract_panel_definitions_from_model_class
@ -157,6 +158,11 @@ def edit(request, content_type_app_name, content_type_model_name, id):
edit_handler_class = get_snippet_edit_handler(model)
form_class = edit_handler_class.get_form_class(model)
usage_url = reverse('wagtailsnippets_usage',
args=(content_type_app_name,
content_type_model_name,
id))
if request.POST:
form = form_class(request.POST, request.FILES, instance=instance)
@ -183,6 +189,7 @@ def edit(request, content_type_app_name, content_type_model_name, id):
'snippet_type_name': snippet_type_name,
'instance': instance,
'edit_handler': edit_handler,
'usage_url': usage_url
})
@ -213,3 +220,14 @@ 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)
return render(request, "wagtailsnippets/snippets/usage.html", {
'instance': instance,
})