289 lines
9.2 KiB
Python
289 lines
9.2 KiB
Python
|
|
from django.core.paginator import Paginator
|
||
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
||
|
|
from django.urls import reverse
|
||
|
|
from django.utils.text import capfirst
|
||
|
|
from django.utils.translation import gettext as _
|
||
|
|
from django.views.decorators.vary import vary_on_headers
|
||
|
|
from wagtail.admin import messages
|
||
|
|
from wagtail.admin.admin_url_finder import AdminURLFinder
|
||
|
|
from wagtail.admin.auth import PermissionPolicyChecker, permission_denied
|
||
|
|
from wagtail.admin.forms.search import SearchForm
|
||
|
|
from wagtail.admin.models import popular_tags_for_model
|
||
|
|
from wagtail.models import Collection, Page
|
||
|
|
from wagtail.search.backends import get_search_backends
|
||
|
|
|
||
|
|
from wagtailmedia.forms import get_media_form
|
||
|
|
from wagtailmedia.models import get_media_model
|
||
|
|
from wagtailmedia.permissions import permission_policy
|
||
|
|
from wagtailmedia.utils import paginate
|
||
|
|
|
||
|
|
|
||
|
|
permission_checker = PermissionPolicyChecker(permission_policy)
|
||
|
|
|
||
|
|
|
||
|
|
@permission_checker.require_any("add", "change", "delete")
|
||
|
|
@vary_on_headers("X-Requested-With")
|
||
|
|
def index(request):
|
||
|
|
Media = get_media_model()
|
||
|
|
|
||
|
|
# Get media files (filtered by user permission)
|
||
|
|
media = permission_policy.instances_user_has_any_permission_for(
|
||
|
|
request.user, ["change", "delete"]
|
||
|
|
)
|
||
|
|
|
||
|
|
# Ordering
|
||
|
|
if request.GET.get("ordering") in ["title", "-title", "-created_at", "created_at"]:
|
||
|
|
ordering = request.GET["ordering"]
|
||
|
|
else:
|
||
|
|
ordering = "-created_at"
|
||
|
|
media = media.order_by(ordering)
|
||
|
|
|
||
|
|
# Filter by collection
|
||
|
|
current_collection = None
|
||
|
|
collection_id = request.GET.get("collection_id")
|
||
|
|
if collection_id:
|
||
|
|
try:
|
||
|
|
current_collection = Collection.objects.get(id=collection_id)
|
||
|
|
media = media.filter(collection=current_collection)
|
||
|
|
except (ValueError, Collection.DoesNotExist):
|
||
|
|
pass
|
||
|
|
|
||
|
|
# Search
|
||
|
|
query_string = ""
|
||
|
|
if "q" in request.GET and request.GET.get("q").strip():
|
||
|
|
form = SearchForm(request.GET, placeholder=_("Search media files"))
|
||
|
|
if form.is_valid():
|
||
|
|
query_string = form.cleaned_data["q"]
|
||
|
|
media = media.search(query_string)
|
||
|
|
else:
|
||
|
|
form = SearchForm(placeholder=_("Search media"))
|
||
|
|
|
||
|
|
# Filter by tag
|
||
|
|
if current_tag := request.GET.get("tag"):
|
||
|
|
try:
|
||
|
|
media = media.filter(tags__name=current_tag)
|
||
|
|
except AttributeError:
|
||
|
|
current_tag = None
|
||
|
|
|
||
|
|
# Pagination
|
||
|
|
paginator, media = paginate(request, media)
|
||
|
|
|
||
|
|
collections = permission_policy.collections_user_has_any_permission_for(
|
||
|
|
request.user, ["add", "change"]
|
||
|
|
)
|
||
|
|
if len(collections) < 2:
|
||
|
|
collections = None
|
||
|
|
|
||
|
|
# Create response
|
||
|
|
if request.headers.get("x-requested-with") == "XMLHttpRequest":
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/results.html",
|
||
|
|
{
|
||
|
|
"ordering": ordering,
|
||
|
|
"media_files": media,
|
||
|
|
"query_string": query_string,
|
||
|
|
"is_searching": bool(query_string),
|
||
|
|
"collections": collections,
|
||
|
|
},
|
||
|
|
)
|
||
|
|
else:
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/index.html",
|
||
|
|
{
|
||
|
|
"ordering": ordering,
|
||
|
|
"media_files": media,
|
||
|
|
"query_string": query_string,
|
||
|
|
"is_searching": bool(query_string),
|
||
|
|
"search_form": form,
|
||
|
|
"popular_tags": popular_tags_for_model(Media),
|
||
|
|
"current_tag": current_tag,
|
||
|
|
"user_can_add": permission_policy.user_has_permission(
|
||
|
|
request.user, "add"
|
||
|
|
),
|
||
|
|
"collections": collections,
|
||
|
|
"current_collection": current_collection,
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@permission_checker.require("add")
|
||
|
|
def add(request, media_type):
|
||
|
|
Media = get_media_model()
|
||
|
|
MediaForm = get_media_form(Media)
|
||
|
|
|
||
|
|
if request.method == "POST":
|
||
|
|
media = Media(uploaded_by_user=request.user, type=media_type)
|
||
|
|
form = MediaForm(request.POST, request.FILES, instance=media, user=request.user)
|
||
|
|
if form.is_valid():
|
||
|
|
form.save()
|
||
|
|
|
||
|
|
# Reindex the media entry to make sure all tags are indexed
|
||
|
|
for backend in get_search_backends():
|
||
|
|
backend.add(media)
|
||
|
|
|
||
|
|
messages.success(
|
||
|
|
request,
|
||
|
|
_("Media file '{0}' added.").format(media.title),
|
||
|
|
buttons=[
|
||
|
|
messages.button(
|
||
|
|
reverse("wagtailmedia:edit", args=(media.id,)), _("Edit")
|
||
|
|
)
|
||
|
|
],
|
||
|
|
)
|
||
|
|
return redirect("wagtailmedia:index")
|
||
|
|
else:
|
||
|
|
messages.error(
|
||
|
|
request, _("The media file could not be saved due to errors.")
|
||
|
|
)
|
||
|
|
else:
|
||
|
|
media = Media(uploaded_by_user=request.user, type=media_type)
|
||
|
|
form = MediaForm(user=request.user, instance=media)
|
||
|
|
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/add.html",
|
||
|
|
{
|
||
|
|
"form": form,
|
||
|
|
"media_type": media_type,
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@permission_checker.require("change")
|
||
|
|
def edit(request, media_id):
|
||
|
|
Media = get_media_model()
|
||
|
|
MediaForm = get_media_form(Media)
|
||
|
|
|
||
|
|
media = get_object_or_404(Media, id=media_id)
|
||
|
|
|
||
|
|
if not permission_policy.user_has_permission_for_instance(
|
||
|
|
request.user, "change", media
|
||
|
|
):
|
||
|
|
return permission_denied(request)
|
||
|
|
|
||
|
|
if request.method == "POST":
|
||
|
|
original_file = media.file
|
||
|
|
form = MediaForm(request.POST, request.FILES, instance=media, user=request.user)
|
||
|
|
if form.is_valid():
|
||
|
|
if "file" in form.changed_data:
|
||
|
|
# if providing a new media file, delete the old one.
|
||
|
|
# NB Doing this via original_file.delete() clears the file field,
|
||
|
|
# which definitely isn't what we want...
|
||
|
|
original_file.storage.delete(original_file.name)
|
||
|
|
media = form.save()
|
||
|
|
|
||
|
|
# Reindex the media entry to make sure all tags are indexed
|
||
|
|
for backend in get_search_backends():
|
||
|
|
backend.add(media)
|
||
|
|
|
||
|
|
messages.success(
|
||
|
|
request,
|
||
|
|
_("Media file '{0}' updated").format(media.title),
|
||
|
|
buttons=[
|
||
|
|
messages.button(
|
||
|
|
reverse("wagtailmedia:edit", args=(media.id,)), _("Edit")
|
||
|
|
)
|
||
|
|
],
|
||
|
|
)
|
||
|
|
return redirect("wagtailmedia:index")
|
||
|
|
else:
|
||
|
|
messages.error(request, _("The media could not be saved due to errors."))
|
||
|
|
else:
|
||
|
|
form = MediaForm(instance=media, user=request.user)
|
||
|
|
|
||
|
|
filesize = None
|
||
|
|
|
||
|
|
# Get file size when there is a file associated with the Media object
|
||
|
|
if media.file:
|
||
|
|
try:
|
||
|
|
filesize = media.file.size
|
||
|
|
except OSError:
|
||
|
|
# File doesn't exist
|
||
|
|
pass
|
||
|
|
|
||
|
|
if not filesize:
|
||
|
|
messages.error(
|
||
|
|
request,
|
||
|
|
_(
|
||
|
|
"The file could not be found. Please change the source or delete the media file"
|
||
|
|
),
|
||
|
|
buttons=[
|
||
|
|
messages.button(
|
||
|
|
reverse("wagtailmedia:delete", args=(media.id,)), _("Delete")
|
||
|
|
)
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/edit.html",
|
||
|
|
{
|
||
|
|
"media": media,
|
||
|
|
"filesize": filesize,
|
||
|
|
"form": form,
|
||
|
|
"user_can_delete": permission_policy.user_has_permission_for_instance(
|
||
|
|
request.user, "delete", media
|
||
|
|
),
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@permission_checker.require("delete")
|
||
|
|
def delete(request, media_id):
|
||
|
|
Media = get_media_model()
|
||
|
|
media = get_object_or_404(Media, id=media_id)
|
||
|
|
|
||
|
|
if not permission_policy.user_has_permission_for_instance(
|
||
|
|
request.user, "delete", media
|
||
|
|
):
|
||
|
|
return permission_denied(request)
|
||
|
|
|
||
|
|
if request.method == "POST":
|
||
|
|
media.delete()
|
||
|
|
messages.success(request, _("Media file '{0}' deleted.").format(media.title))
|
||
|
|
return redirect("wagtailmedia:index")
|
||
|
|
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/confirm_delete.html",
|
||
|
|
{
|
||
|
|
"media": media,
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@permission_checker.require_any("add", "change", "delete")
|
||
|
|
def usage(request, media_id):
|
||
|
|
Media = get_media_model()
|
||
|
|
media_item = get_object_or_404(Media, id=media_id)
|
||
|
|
|
||
|
|
paginator = Paginator(media_item.get_usage(), per_page=20)
|
||
|
|
object_page = paginator.get_page(request.GET.get("p"))
|
||
|
|
|
||
|
|
# Add edit URLs to each source object
|
||
|
|
url_finder = AdminURLFinder(request.user)
|
||
|
|
results = []
|
||
|
|
for entity, references in object_page:
|
||
|
|
edit_url = url_finder.get_edit_url(entity)
|
||
|
|
if edit_url is None:
|
||
|
|
label = _("(Private %s)") % entity._meta.verbose_name
|
||
|
|
edit_link_title = None
|
||
|
|
else:
|
||
|
|
label = str(entity)
|
||
|
|
edit_link_title = _("Edit this %s") % entity._meta.verbose_name
|
||
|
|
|
||
|
|
if isinstance(entity, Page):
|
||
|
|
verbose_name = capfirst(entity.specific_class._meta.verbose_name)
|
||
|
|
else:
|
||
|
|
verbose_name = capfirst(entity._meta.verbose_name)
|
||
|
|
|
||
|
|
results.append((label, edit_url, edit_link_title, verbose_name, references))
|
||
|
|
|
||
|
|
return render(
|
||
|
|
request,
|
||
|
|
"wagtailmedia/media/usage.html",
|
||
|
|
{"media_item": media_item, "results": results, "object_page": object_page},
|
||
|
|
)
|