@@ -271,3 +271,171 @@ from viewflow.models import Process, Task
271271~~ admin.site.register(Process, ProcessAdmin)
272272~~ admin.site.register(Task, TaskAdmin)
273273```
274+
275+
276+ ## Example 4 from django-filer
277+ [ django-filer] ( https://github.com/divio/django-filer )
278+ ([ project documentation] ( https://django-filer.readthedocs.io/en/latest/ ) )
279+ is a file management library for uploading and organizing files and
280+ images in Django's admin interface.
281+
282+ The project's code is available under the
283+ [ BSD 3-Clause "New" or "Revised" open source license] ( https://github.com/divio/django-filer/blob/develop/LICENSE.txt ) .
284+
285+ [ ** django-filer / filer / admin / fileadmin.py** ] ( https://github.com/divio/django-filer/blob/develop/filer/admin/fileadmin.py )
286+
287+ ``` python
288+ # -*- coding: utf-8 -*-
289+ from __future__ import absolute_import
290+
291+ from django import forms
292+ from django.contrib.admin.utils import unquote
293+ from django.http import HttpResponseRedirect
294+ from django.urls import reverse
295+ from django.utils.safestring import mark_safe
296+ from django.utils.translation import ugettext as _
297+
298+ from .. import settings
299+ from ..models import File
300+ ~~ from .permissions import PrimitivePermissionAwareModelAdmin
301+ ~~ from .tools import AdminContext, admin_url_params_encoded, popup_status
302+
303+
304+ ~~ class FileAdminChangeFrom (forms .ModelForm ):
305+ class Meta (object ):
306+ model = File
307+ exclude = ()
308+
309+
310+ ~~ class FileAdmin (PrimitivePermissionAwareModelAdmin ):
311+ list_display = (' label' ,)
312+ list_per_page = 10
313+ search_fields = [' name' , ' original_filename' , ' sha1' , ' description' ]
314+ raw_id_fields = (' owner' ,)
315+ readonly_fields = (' sha1' , ' display_canonical' )
316+
317+ form = FileAdminChangeFrom
318+
319+ @ classmethod
320+ def build_fieldsets (cls , extra_main_fields = (), extra_advanced_fields = (),
321+ extra_fieldsets = ()):
322+ fieldsets = (
323+ (None , {
324+ ' fields' : (
325+ ' name' ,
326+ ' owner' ,
327+ ' description' ,
328+ ) + extra_main_fields,
329+ }),
330+ (_(' Advanced' ), {
331+ ' fields' : (
332+ ' file' ,
333+ ' sha1' ,
334+ ' display_canonical' ,
335+ ) + extra_advanced_fields,
336+ ' classes' : (' collapse' ,),
337+ }),
338+ ) + extra_fieldsets
339+ if settings.FILER_ENABLE_PERMISSIONS :
340+ fieldsets = fieldsets + (
341+ (None , {
342+ ' fields' : (' is_public' ,)
343+ }),
344+ )
345+ return fieldsets
346+
347+ def response_change (self , request , obj ):
348+ """
349+ Overrides the default to be able to forward to the directory listing
350+ instead of the default change_list_view
351+ """
352+ if (
353+ request.POST
354+ and ' _continue' not in request.POST
355+ and ' _saveasnew' not in request.POST
356+ and ' _addanother' not in request.POST
357+ ):
358+ # Popup in pick mode or normal mode. In both cases we want to go
359+ # back to the folder list view after save. And not the useless file
360+ # list view.
361+ if obj.folder:
362+ url = reverse(' admin:filer-directory_listing' ,
363+ kwargs = {' folder_id' : obj.folder.id})
364+ else :
365+ url = reverse(
366+ ' admin:filer-directory_listing-unfiled_images' )
367+ url = " {0}{1} " .format(
368+ url,
369+ admin_url_params_encoded(request),
370+ )
371+ return HttpResponseRedirect(url)
372+ return super (FileAdmin, self ).response_change(request, obj)
373+
374+ def render_change_form (self , request , context , add = False , change = False ,
375+ form_url = ' ' , obj = None ):
376+ info = self .model._meta.app_label, self .model._meta.model_name
377+ extra_context = {' show_delete' : True ,
378+ ' history_url' : ' admin:%s _%s _history' % info,
379+ ' is_popup' : popup_status(request),
380+ ' filer_admin_context' : AdminContext(request)}
381+ context.update(extra_context)
382+ return super (FileAdmin, self ).render_change_form(
383+ request = request, context = context, add = add, change = change,
384+ form_url = form_url, obj = obj)
385+
386+ def delete_view (self , request , object_id , extra_context = None ):
387+ """
388+ Overrides the default to enable redirecting to the directory view after
389+ deletion of a image.
390+ we need to fetch the object and find out who the parent is
391+ before super, because super will delete the object and make it
392+ impossible to find out the parent folder to redirect to.
393+ """
394+ try :
395+ obj = self .get_queryset(request).get(pk = unquote(object_id))
396+ parent_folder = obj.folder
397+ except self .model.DoesNotExist:
398+ parent_folder = None
399+
400+ if request.POST :
401+ # Return to folder listing, since there is no usable file listing.
402+ super (FileAdmin, self ).delete_view(
403+ request = request, object_id = object_id,
404+ extra_context = extra_context)
405+ if parent_folder:
406+ url = reverse(' admin:filer-directory_listing' ,
407+ kwargs = {' folder_id' : parent_folder.id})
408+ else :
409+ url = reverse(' admin:filer-directory_listing-unfiled_images' )
410+ url = " {0}{1} " .format(
411+ url,
412+ admin_url_params_encoded(request)
413+ )
414+ return HttpResponseRedirect(url)
415+
416+ return super (FileAdmin, self ).delete_view(
417+ request = request, object_id = object_id,
418+ extra_context = extra_context)
419+
420+ def get_model_perms (self , request ):
421+ """
422+ It seems this is only used for the list view. NICE :-)
423+ """
424+ return {
425+ ' add' : False ,
426+ ' change' : False ,
427+ ' delete' : False ,
428+ }
429+
430+ def display_canonical (self , instance ):
431+ canonical = instance.canonical_url
432+ if canonical:
433+ return mark_safe(' <a href="%s ">%s </a>' % (canonical, canonical))
434+ else :
435+ return ' -'
436+ display_canonical.allow_tags = True
437+ display_canonical.short_description = _(' canonical URL' )
438+
439+
440+ ~~ FileAdmin.fieldsets = FileAdmin.build_fieldsets()
441+ ```
0 commit comments