mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-11 00:33:17 +00:00
Add usage counters for images, documents and snippets
This commit is contained in:
parent
26cacbc95a
commit
94e0f74024
17 changed files with 173 additions and 9 deletions
|
|
@ -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>
|
||||
|
|
|
|||
36
wagtail/wagtailadmin/utils.py
Normal file
36
wagtail/wagtailadmin/utils.py
Normal 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
|
||||
|
|
@ -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 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
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
@ -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'),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
@ -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,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,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue