Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize django filer #1344

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,12 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11' ]
python-version: ['3.8', '3.9', '3.10', '3.11']
requirements-file: [
django-2.2.txt,
django-3.0.txt,
django-3.1.txt,
django-3.2.txt,
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm almost certain django 3.2, 4.0 don't support python 3.11, so some exclusions will still be required.

django-4.0.txt,
django-4.1.txt
django-4.1.txt,
]
exclude:
- python-version: 3.7
requirements-file: django-4.0.txt
- python-version: 3.7
requirements-file: django-4.1.txt
- python-version: 3.9
requirements-file: django-2.2.txt
- python-version: 3.10
requirements-file: django-2.2.txt
- python-version: 3.10
requirements-file: django-3.0.txt
- python-version: 3.10
requirements-file: django-3.1.txt
- python-version: 3.11
requirements-file: django-2.2.txt
- python-version: 3.11
requirements-file: django-3.0.txt
- python-version: 3.11
requirements-file: django-3.1.txt
os: [
ubuntu-20.04,
]
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,3 @@ pep8.txt
share/
.python-version
data
local.sqlite
110 changes: 44 additions & 66 deletions filer/admin/folderadmin.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import itertools
import os
import re
from collections import OrderedDict
from urllib.parse import quote as urlquote
from urllib.parse import unquote as urlunquote

from django import forms
from django.conf import settings as django_settings
from django.contrib import messages
from django.contrib.admin import helpers
from django.contrib.admin.decorators import action
from django.contrib.admin.utils import capfirst, quote, unquote
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import models, router
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import re_path, reverse
from django.urls import path, reverse
from django.utils.encoding import force_str
from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
Expand All @@ -35,8 +35,7 @@
from .permissions import PrimitivePermissionAwareModelAdmin
from .tools import (
AdminContext, admin_url_params_encoded, check_files_edit_permissions, check_files_read_permissions,
check_folder_edit_permissions, check_folder_read_permissions, get_directory_listing_type, popup_status,
userperms_for_request,
check_folder_edit_permissions, check_folder_read_permissions, popup_status, userperms_for_request,
)


Expand All @@ -52,10 +51,9 @@ class Meta:


class FolderAdmin(PrimitivePermissionAwareModelAdmin):
list_display = ('name',)
exclude = ('parent',)
list_per_page = 20
list_filter = ('owner',)
list_display = ['name']
exclude = ['parent']
list_filter = ['owner']
search_fields = ['name']
autocomplete_fields = ['owner']
save_as = True # see ImageAdmin
Expand Down Expand Up @@ -201,40 +199,34 @@ def get_urls(self):
return [
# we override the default list view with our own directory listing
# of the root directories
re_path(r'^$',
self.admin_site.admin_view(self.directory_listing),
name='filer-directory_listing-root'),

re_path(r'^last/$',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'last'},
name='filer-directory_listing-last'),

re_path(r'^(?P<folder_id>\d+)/list/$',
self.admin_site.admin_view(self.directory_listing),
name='filer-directory_listing'),

re_path(r'^(?P<folder_id>\d+)/make_folder/$',
self.admin_site.admin_view(views.make_folder),
name='filer-directory_listing-make_folder'),
re_path(r'^make_folder/$',
self.admin_site.admin_view(views.make_folder),
name='filer-directory_listing-make_root_folder'),

re_path(r'^images_with_missing_data/$',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'images_with_missing_data'},
name='filer-directory_listing-images_with_missing_data'),

re_path(r'^unfiled_images/$',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'unfiled_images'},
name='filer-directory_listing-unfiled_images'),
path('',
self.admin_site.admin_view(self.directory_listing),
name='filer-directory_listing-root'),
path('last/',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'last'},
name='filer-directory_listing-last'),
path('<int:folder_id>/list/',
self.admin_site.admin_view(self.directory_listing),
name='filer-directory_listing'),
path('<int:folder_id>/make_folder/',
self.admin_site.admin_view(views.make_folder),
name='filer-directory_listing-make_folder'),
path('make_folder/',
self.admin_site.admin_view(views.make_folder),
name='filer-directory_listing-make_root_folder'),
path('images_with_missing_data/',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'images_with_missing_data'},
name='filer-directory_listing-images_with_missing_data'),
path('unfiled_images/',
self.admin_site.admin_view(self.directory_listing),
{'viewtype': 'unfiled_images'},
name='filer-directory_listing-unfiled_images'),
] + super().get_urls()

# custom views
def directory_listing(self, request, folder_id=None, viewtype=None):
clipboard = tools.get_user_clipboard(request.user)
if viewtype == 'images_with_missing_data':
folder = ImagesWithMissingData()
elif viewtype == 'unfiled_images':
Expand Down Expand Up @@ -407,7 +399,6 @@ def directory_listing(self, request, folder_id=None, viewtype=None):
except EmptyPage:
paginated_items = paginator.page(paginator.num_pages)

list_type = get_directory_listing_type(request) or settings.FILER_FOLDER_ADMIN_DEFAULT_LIST_TYPE
context = self.admin_site.each_context(request)
context.update({
'folder': folder,
Expand Down Expand Up @@ -438,8 +429,6 @@ def directory_listing(self, request, folder_id=None, viewtype=None):
'actions_selection_counter': self.actions_selection_counter,
'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(paginated_items.object_list)},
'selection_note_all': selection_note_all % {'total_count': paginator.count},
'list_type': list_type,
'list_type_template': settings.FILER_FOLDER_ADMIN_LIST_TYPE_SWITCHER_SETTINGS[list_type]['template'],
'media': self.media,
'enable_permissions': settings.FILER_ENABLE_PERMISSIONS,
'can_make_folder': request.user.is_superuser or (folder.is_root and settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS) or permissions.get("has_add_children_permission"),
Expand Down Expand Up @@ -578,18 +567,18 @@ def response_action(self, request, files_queryset, folders_queryset):
return None

def get_actions(self, request):
actions = super().get_actions(request)
if settings.FILER_ENABLE_PERMISSIONS:
actions = OrderedDict()
actions['files_set_public'] = self.get_action('files_set_public')
actions['files_set_private'] = self.get_action('files_set_private')
actions.update(super().get_actions(request))
else:
actions = super().get_actions(request)
actions.update(
files_set_public=self.get_action('files_set_public'),
files_set_private=self.get_action('files_set_private'),
)

if 'delete_selected' in actions:
del actions['delete_selected']
return actions

@action(description=_("Move selected files to clipboard"))
def move_to_clipboard(self, request, files_queryset, folders_queryset):
"""
Action which moves the selected files and files in selected folders
Expand Down Expand Up @@ -628,10 +617,6 @@ def move_folders(folders):
self.message_user(request, _("Successfully moved %(count)d files to "
"clipboard.") % {"count": files_count[0]})

return None

move_to_clipboard.short_description = _("Move selected files to clipboard")

def files_set_public_or_private(self, request, set_public, files_queryset,
folders_queryset):
"""
Expand Down Expand Up @@ -676,18 +661,17 @@ def set_folders(folders):

return None

@action(description=_("Enable permissions for selected files"))
def files_set_private(self, request, files_queryset, folders_queryset):
return self.files_set_public_or_private(request, False, files_queryset,
folders_queryset)

files_set_private.short_description = _("Enable permissions for selected files")

@action(description=_("Disable permissions for selected files"))
def files_set_public(self, request, files_queryset, folders_queryset):
return self.files_set_public_or_private(request, True, files_queryset,
folders_queryset)

files_set_public.short_description = _("Disable permissions for selected files")

@action(description=_("Delete selected files and/or folders"))
def delete_files_or_folders(self, request, files_queryset, folders_queryset):
"""
Action which deletes the selected files and/or folders.
Expand Down Expand Up @@ -785,8 +769,6 @@ def delete_files_or_folders(self, request, files_queryset, folders_queryset):
context
)

delete_files_or_folders.short_description = _("Delete selected files and/or folders")

# Copied from django.contrib.admin.util
def _format_callback(self, obj, user, admin_site, perms_needed):
has_admin = obj.__class__ in admin_site._registry
Expand Down Expand Up @@ -864,7 +846,7 @@ def _list_all_destination_folders_recursive(self, request, folders_queryset, cur

def _list_all_destination_folders(self, request, folders_queryset, current_folder, allow_self):
root_folders = self.get_queryset(request).filter(parent__isnull=True).order_by('name')
return list(self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, root_folders, allow_self, 0))
return self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, root_folders, allow_self, 0)

def _move_files_and_folders_impl(self, files_queryset, folders_queryset, destination):
for f in files_queryset:
Expand All @@ -874,6 +856,7 @@ def _move_files_and_folders_impl(self, files_queryset, folders_queryset, destina
f.move_to(destination, 'last-child')
f.save()

@action(description=_("Move selected files and/or folders"))
def move_files_and_folders(self, request, files_queryset, folders_queryset):
opts = self.model._meta
app_label = opts.app_label
Expand Down Expand Up @@ -926,8 +909,6 @@ def move_files_and_folders(self, request, files_queryset, folders_queryset):
# Display the destination folder selection page
return render(request, "admin/filer/folder/choose_move_destination.html", context)

move_files_and_folders.short_description = _("Move selected files and/or folders")

def _rename_file(self, file_obj, form_data, counter, global_counter):
original_basename, original_extension = os.path.splitext(file_obj.original_filename)
if file_obj.name:
Expand Down Expand Up @@ -968,6 +949,7 @@ def _rename_files_impl(self, files_queryset, folders_queryset, form_data, global

return n

@action(description=_("Rename files"))
def rename_files(self, request, files_queryset, folders_queryset):
opts = self.model._meta
app_label = opts.app_label
Expand Down Expand Up @@ -1009,8 +991,6 @@ def rename_files(self, request, files_queryset, folders_queryset):
# Display the rename format selection page
return render(request, "admin/filer/folder/choose_rename_format.html", context)

rename_files.short_description = _("Rename files")

def _generate_new_filename(self, filename, suffix):
basename, extension = os.path.splitext(filename)
return basename + suffix + extension
Expand Down Expand Up @@ -1080,6 +1060,7 @@ def _copy_files_and_folders_impl(self, files_queryset, folders_queryset, destina

return n

@action(description=_("Copy selected files and/or folders"))
def copy_files_and_folders(self, request, files_queryset, folders_queryset):
opts = self.model._meta
app_label = opts.app_label
Expand Down Expand Up @@ -1141,8 +1122,6 @@ def copy_files_and_folders(self, request, files_queryset, folders_queryset):
# Display the destination folder selection page
return render(request, "admin/filer/folder/choose_copy_destination.html", context)

copy_files_and_folders.short_description = _("Copy selected files and/or folders")

def _check_resize_perms(self, request, files_queryset, folders_queryset):
try:
check_files_read_permissions(request, files_queryset)
Expand Down Expand Up @@ -1225,6 +1204,7 @@ def _resize_images_impl(self, files_queryset, folders_queryset, form_data):

return n

@action(description=_("Resize selected images"))
def resize_images(self, request, files_queryset, folders_queryset):
opts = self.model._meta
app_label = opts.app_label
Expand Down Expand Up @@ -1270,5 +1250,3 @@ def resize_images(self, request, files_queryset, folders_queryset):

# Display the resize options page
return render(request, "admin/filer/folder/choose_images_resize_options.html", context)

resize_images.short_description = _("Resize selected images")
12 changes: 0 additions & 12 deletions filer/admin/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from django.core.exceptions import PermissionDenied
from django.utils.http import urlencode

from .. import settings


ALLOWED_PICK_TYPES = ('folder', 'file')

Expand Down Expand Up @@ -66,13 +64,6 @@ def popup_pick_type(request):
return None


def get_directory_listing_type(request):
list_type = request.GET.get('_list_type', None)
if list_type not in settings.FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES:
return
return list_type


def admin_url_params(request, params=None):
"""
given a request, looks at GET and POST values to determine which params
Expand All @@ -84,9 +75,6 @@ def admin_url_params(request, params=None):
pick_type = popup_pick_type(request)
if pick_type:
params['_pick'] = pick_type
list_type = get_directory_listing_type(request)
if list_type and '_list_type' not in params.keys():
params['_list_type'] = list_type
return params


Expand Down
12 changes: 0 additions & 12 deletions filer/private/sass/components/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,3 @@ body {
box-shadow: 0 0 10px -2px rgba(black, 0.2);
background-color: $white;
}

.navigator .actions span.all,
.navigator .actions span.clear,
.navigator .actions span.question {
font-size: 13px;
margin: 0 0.5em;
display: none;
}

#all-items-action-toggle {
display: none !important;
}
Loading
Loading