0
# Template Tags and Utilities
1
2
Django Filer provides template tags for file handling and image processing, plus utility functions for file operations, validation, and thumbnail processing. These components facilitate frontend integration and programmatic file manipulation.
3
4
## Capabilities
5
6
### Template Tags
7
8
Template tags and filters for displaying and manipulating filer objects in Django templates.
9
10
```python { .api }
11
# filer_tags - Core file template tags
12
from filer.templatetags.filer_tags import *
13
14
def filesize(bytes, format='auto1024'):
15
"""
16
Format file size in human-readable format.
17
18
Args:
19
bytes (int): File size in bytes
20
format (str): Format type ('auto1024', 'auto1000', etc.)
21
22
Returns:
23
str: Formatted file size (e.g., "1.5 MB", "2.3 KB")
24
25
Usage:
26
{{ file.size|filesize }}
27
{{ file.size|filesize:"auto1000" }}
28
"""
29
30
# filer_image_tags - Image manipulation template tags
31
from filer.templatetags.filer_image_tags import *
32
33
def extra_padding_x(image, padding):
34
"""
35
Add horizontal padding to image dimensions.
36
37
Args:
38
image: Image object
39
padding (int): Padding amount in pixels
40
41
Returns:
42
int: Image width plus padding
43
44
Usage:
45
{{ image.width|extra_padding_x:10 }}
46
"""
47
48
def extra_padding_x_keep_ratio(image, padding):
49
"""
50
Add horizontal padding to image while maintaining aspect ratio.
51
52
Args:
53
image: Image object
54
padding (int): Padding amount in pixels
55
56
Returns:
57
int: Adjusted image width maintaining aspect ratio
58
59
Usage:
60
{{ image.width|extra_padding_x_keep_ratio:10 }}
61
"""
62
63
def extra_padding_y(image, padding):
64
"""
65
Add vertical padding to image dimensions.
66
67
Args:
68
image: Image object
69
padding (int): Padding amount in pixels
70
71
Returns:
72
int: Image height plus padding
73
74
Usage:
75
{{ image.height|extra_padding_y:5 }}
76
"""
77
78
def extra_padding_y_keep_ratio(image, padding):
79
"""
80
Add vertical padding to image while maintaining aspect ratio.
81
82
Args:
83
image: Image object
84
padding (int): Padding amount in pixels
85
86
Returns:
87
int: Adjusted image height maintaining aspect ratio
88
89
Usage:
90
{{ image.height|extra_padding_y_keep_ratio:5 }}
91
"""
92
93
def divide_x_by(image, divisor):
94
"""
95
Divide image width by specified value.
96
97
Args:
98
image: Image object
99
divisor (int): Value to divide by
100
101
Returns:
102
int: Image width divided by divisor
103
104
Usage:
105
{{ image.width|divide_x_by:2 }}
106
"""
107
108
def divide_y_by(image, divisor):
109
"""
110
Divide image height by specified value.
111
112
Args:
113
image: Image object
114
divisor (int): Value to divide by
115
116
Returns:
117
int: Image height divided by divisor
118
119
Usage:
120
{{ image.height|divide_y_by:3 }}
121
"""
122
123
def divide_xy_by(image, divisor):
124
"""
125
Divide both image dimensions by specified value.
126
127
Args:
128
image: Image object
129
divisor (int): Value to divide by
130
131
Returns:
132
tuple: (width/divisor, height/divisor)
133
134
Usage:
135
{% with dimensions=image|divide_xy_by:2 %}
136
Width: {{ dimensions.0 }}, Height: {{ dimensions.1 }}
137
{% endwith %}
138
"""
139
140
def get_css_position(image):
141
"""
142
Get CSS background-position based on image subject location.
143
144
Args:
145
image: Image object with subject_location
146
147
Returns:
148
str: CSS background-position value (e.g., "50% 30%")
149
150
Usage:
151
<div style="background-position: {{ image|get_css_position }};">
152
"""
153
154
# filer_admin_tags - Admin-specific template tags
155
from filer.templatetags.filer_admin_tags import *
156
157
def filer_actions(cl):
158
"""
159
Render admin action field for bulk operations.
160
161
Args:
162
cl: ChangeList object from admin
163
164
Returns:
165
dict: Context for action template
166
167
Usage:
168
{% filer_actions cl %}
169
"""
170
171
def filer_folder_list_type_switcher(current_list_type):
172
"""
173
Render list view switcher (table/thumbnail).
174
175
Args:
176
current_list_type: Current view type ('tb' or 'th')
177
178
Returns:
179
dict: Context for switcher template
180
181
Usage:
182
{% filer_folder_list_type_switcher 'tb' %}
183
"""
184
185
def filer_admin_context_url_params(context):
186
"""
187
Get URL parameters from admin context.
188
189
Args:
190
context: Template context
191
192
Returns:
193
str: URL query parameters
194
195
Usage:
196
{% filer_admin_context_url_params %}
197
"""
198
199
def filer_has_permission(item, action, request):
200
"""
201
Check user permissions for admin actions.
202
203
Args:
204
item: File or Folder object
205
action: Permission action ('read', 'edit', 'add_children')
206
request: HTTP request with user
207
208
Returns:
209
bool: True if user has permission
210
211
Usage:
212
{% filer_has_permission item 'edit' request %}
213
"""
214
215
def file_icon(file, detail=False, size=None):
216
"""
217
Render file icon for admin interface.
218
219
Args:
220
file: File object
221
detail: Show detailed icon (bool)
222
size: Icon size override
223
224
Returns:
225
str: Icon HTML
226
227
Usage:
228
{% file_icon file detail=True size=48 %}
229
"""
230
```
231
232
### File Utilities
233
234
Utility functions for file handling, upload processing, and filename generation.
235
236
```python { .api }
237
from filer.utils.files import *
238
239
def handle_upload(request):
240
"""
241
Process file upload from request.
242
243
Args:
244
request: Django HTTP request with file upload
245
246
Returns:
247
File: Created filer File object
248
249
Raises:
250
UploadException: If upload processing fails
251
"""
252
253
def get_valid_filename(filename):
254
"""
255
Generate a valid, safe filename from input string.
256
257
Args:
258
filename (str): Original filename
259
260
Returns:
261
str: Sanitized filename safe for filesystem
262
"""
263
264
def slugify(value):
265
"""
266
Convert string to filename-safe slug.
267
268
Args:
269
value (str): Input string
270
271
Returns:
272
str: Slugified string suitable for filenames
273
"""
274
275
class UploadException(Exception):
276
"""Exception raised during file upload processing."""
277
278
# Filename generation functions
279
from filer.utils.generate_filename import *
280
281
def randomized(instance, filename):
282
"""
283
Generate randomized filename for file uploads.
284
285
Args:
286
instance: Model instance
287
filename (str): Original filename
288
289
Returns:
290
str: Randomized filename preserving extension
291
"""
292
293
def by_date(instance, filename):
294
"""
295
Generate date-based filename for file uploads.
296
297
Args:
298
instance: Model instance
299
filename (str): Original filename
300
301
Returns:
302
str: Date-based filename with YYYY/MM/DD structure
303
"""
304
305
def prefixed_factory(upload_to, prefix):
306
"""
307
Create upload path generator with prefix.
308
309
Args:
310
upload_to: Base upload function
311
prefix (str): Prefix to add to paths
312
313
Returns:
314
function: Upload path generator function
315
"""
316
317
# Loading utilities
318
from filer.utils.loader import *
319
320
def load_object(import_path):
321
"""
322
Import object from dotted path string.
323
324
Args:
325
import_path (str): Dotted path to object (e.g., 'myapp.models.MyModel')
326
327
Returns:
328
object: Imported object
329
330
Raises:
331
ImportError: If import fails
332
"""
333
334
def load_model(model_string):
335
"""
336
Load Django model by string.
337
338
Args:
339
model_string (str): Model string (e.g., 'auth.User')
340
341
Returns:
342
Model: Django model class
343
"""
344
345
def storage_factory(klass, location=None, base_url=None):
346
"""
347
Create storage instance from class and parameters.
348
349
Args:
350
klass: Storage class or import path
351
location: Storage location path
352
base_url: Base URL for storage
353
354
Returns:
355
Storage: Configured storage instance
356
"""
357
```
358
359
### Validation Functions
360
361
File validation utilities for security and content validation.
362
363
```python { .api }
364
from filer.validation import *
365
366
def validate_upload(file_obj):
367
"""
368
Main file upload validation function.
369
370
Args:
371
file_obj: File object to validate
372
373
Raises:
374
FileValidationError: If file fails validation
375
ValidationError: If file violates Django validation rules
376
"""
377
378
def validate_svg(file_obj):
379
"""
380
Security validation for SVG files.
381
382
Args:
383
file_obj: SVG file object to validate
384
385
Raises:
386
FileValidationError: If SVG contains dangerous content
387
"""
388
389
def deny(message="File type not allowed"):
390
"""
391
Validation denial function.
392
393
Args:
394
message (str): Error message
395
396
Raises:
397
FileValidationError: Always raises with provided message
398
"""
399
400
def deny_html(file_obj):
401
"""
402
Validation function to deny HTML files.
403
404
Args:
405
file_obj: File object to check
406
407
Raises:
408
FileValidationError: If file is HTML content
409
"""
410
411
class FileValidationError(Exception):
412
"""Custom exception for file validation errors."""
413
```
414
415
### Cache Functions
416
417
Folder permission caching utilities for performance optimization.
418
419
```python { .api }
420
from filer.cache import *
421
422
def get_folder_permission_cache(user, permission_type):
423
"""
424
Retrieve cached folder permissions for user.
425
426
Args:
427
user: Django User object
428
permission_type (str): Type of permission ('can_read', 'can_edit', 'can_add_children')
429
430
Returns:
431
set or None: Set of folder IDs or None if not cached
432
"""
433
434
def update_folder_permission_cache(user, permission_type, folder_ids):
435
"""
436
Update folder permission cache for user.
437
438
Args:
439
user: Django User object
440
permission_type (str): Type of permission
441
folder_ids (set): Set of folder IDs user has permission for
442
"""
443
444
def clear_folder_permission_cache(user=None):
445
"""
446
Clear folder permission cache.
447
448
Args:
449
user (optional): Specific user to clear cache for, or None for all users
450
"""
451
```
452
453
### Thumbnail Processors
454
455
Image processing functions for thumbnail generation with easy-thumbnails integration.
456
457
```python { .api }
458
from filer.thumbnail_processors import *
459
460
def scale_and_crop_with_subject_location(im, requested_size, opts):
461
"""
462
Scale and crop image considering subject location for smart cropping.
463
464
Args:
465
im: PIL Image object
466
requested_size (tuple): Target (width, height)
467
opts (dict): Processing options
468
469
Returns:
470
PIL.Image: Processed image
471
472
Usage in THUMBNAIL_PROCESSORS:
473
'filer.thumbnail_processors.scale_and_crop_with_subject_location'
474
"""
475
476
def whitespace(im, requested_size, opts):
477
"""
478
Add whitespace padding to image instead of cropping.
479
480
Args:
481
im: PIL Image object
482
requested_size (tuple): Target (width, height)
483
opts (dict): Processing options including background color
484
485
Returns:
486
PIL.Image: Image with whitespace padding
487
488
Usage in THUMBNAIL_PROCESSORS:
489
'filer.thumbnail_processors.whitespace'
490
"""
491
```
492
493
### Storage Classes
494
495
Storage backend classes for handling public and private file storage.
496
497
```python { .api }
498
from filer.storage import *
499
500
class PublicFileSystemStorage(FileSystemStorage):
501
"""
502
Storage class for public files accessible via direct URL.
503
504
Configured via FILER_PUBLICMEDIA_* settings.
505
"""
506
507
class PrivateFileSystemStorage(FileSystemStorage):
508
"""
509
Storage class for private files requiring permission checks.
510
511
Configured via FILER_PRIVATEMEDIA_* settings.
512
Files served through Django views with permission validation.
513
"""
514
```
515
516
## Usage Examples
517
518
### Template Usage
519
520
```django
521
{# Load template tags #}
522
{% load filer_tags %}
523
{% load filer_image_tags %}
524
525
{# Display file information #}
526
{% if article.attachment %}
527
<div class="file-attachment">
528
<a href="{{ article.attachment.url }}">
529
{{ article.attachment.name }}
530
</a>
531
<span class="file-size">({{ article.attachment.size|filesize }})</span>
532
</div>
533
{% endif %}
534
535
{# Display image with responsive sizing #}
536
{% if article.featured_image %}
537
<div class="featured-image">
538
<img src="{{ article.featured_image.url }}"
539
alt="{{ article.featured_image.default_alt_text }}"
540
width="{{ article.featured_image.width|divide_x_by:2 }}"
541
height="{{ article.featured_image.height|divide_y_by:2 }}" />
542
543
{# Image with subject-aware background positioning #}
544
<div class="hero-image"
545
style="background-image: url('{{ article.featured_image.url }}');
546
background-position: {{ article.featured_image|get_css_position }};">
547
</div>
548
</div>
549
{% endif %}
550
551
{# File listing with metadata #}
552
{% for file in folder.files %}
553
<div class="file-item">
554
<h4>{{ file.name }}</h4>
555
<p>Size: {{ file.size|filesize }}</p>
556
<p>Type: {{ file.mime_type }}</p>
557
{% if file.description %}
558
<p>{{ file.description }}</p>
559
{% endif %}
560
561
{# Show thumbnail for images #}
562
{% if file.file_type == 'Image' %}
563
<img src="{{ file.icons.48 }}" alt="Thumbnail" />
564
<p>Dimensions: {{ file.width }}x{{ file.height }}</p>
565
{% endif %}
566
</div>
567
{% endfor %}
568
```
569
570
### Programmatic File Handling
571
572
```python
573
from filer.utils.files import handle_upload, get_valid_filename
574
from filer.models import File, Folder
575
from django.core.files.base import ContentFile
576
577
def process_user_upload(request):
578
"""Process file upload with validation and organization."""
579
try:
580
# Handle upload from request
581
uploaded_file = handle_upload(request)
582
583
# Generate safe filename
584
safe_name = get_valid_filename(uploaded_file.name)
585
586
# Organize into user folder
587
user_folder, created = Folder.objects.get_or_create(
588
name=f"User_{request.user.id}_Files",
589
owner=request.user
590
)
591
592
# Create file object
593
file_obj = File.objects.create(
594
file=uploaded_file.file,
595
name=safe_name,
596
folder=user_folder,
597
owner=request.user,
598
is_public=False # Private by default
599
)
600
601
return file_obj
602
603
except UploadException as e:
604
# Handle upload errors
605
logger.error(f"Upload failed: {e}")
606
return None
607
608
def bulk_process_files(file_paths):
609
"""Process multiple files programmatically."""
610
processed_files = []
611
612
for file_path in file_paths:
613
with open(file_path, 'rb') as f:
614
content = ContentFile(f.read())
615
616
# Generate safe filename
617
filename = get_valid_filename(os.path.basename(file_path))
618
619
file_obj = File.objects.create(
620
file=content,
621
name=filename,
622
original_filename=os.path.basename(file_path)
623
)
624
625
processed_files.append(file_obj)
626
627
return processed_files
628
```
629
630
### Custom Validation
631
632
```python
633
from filer.validation import FileValidationError
634
from django.core.exceptions import ValidationError
635
636
def custom_image_validator(file_obj):
637
"""Custom validator for image files."""
638
if not file_obj.mime_type.startswith('image/'):
639
return # Only validate images
640
641
# Check image dimensions
642
if hasattr(file_obj, 'width') and hasattr(file_obj, 'height'):
643
if file_obj.width < 100 or file_obj.height < 100:
644
raise FileValidationError("Image must be at least 100x100 pixels")
645
646
if file_obj.width > 4000 or file_obj.height > 4000:
647
raise FileValidationError("Image must not exceed 4000x4000 pixels")
648
649
# Check file size
650
if file_obj.size > 5 * 1024 * 1024: # 5MB
651
raise FileValidationError("Image file must not exceed 5MB")
652
653
def corporate_filename_validator(file_obj):
654
"""Ensure corporate naming standards."""
655
import re
656
657
# Check for valid corporate filename pattern
658
if not re.match(r'^[A-Z][A-Za-z0-9_-]+\.[a-z]+$', file_obj.name):
659
raise FileValidationError(
660
"Filename must start with capital letter and contain only "
661
"letters, numbers, hyphens, and underscores"
662
)
663
664
# Register custom validators in settings.py
665
FILE_VALIDATORS = [
666
'filer.validation.validate_upload',
667
'myapp.validators.custom_image_validator',
668
'myapp.validators.corporate_filename_validator',
669
]
670
```
671
672
### Permission-Aware Template Tags
673
674
```python
675
# Custom template tags for permission checking
676
from django import template
677
from filer.models import File, Folder
678
679
register = template.Library()
680
681
@register.filter
682
def user_can_access(file_obj, user):
683
"""Check if user can access file."""
684
return file_obj.has_read_permission(user)
685
686
@register.filter
687
def user_can_edit(file_obj, user):
688
"""Check if user can edit file."""
689
return file_obj.has_edit_permission(user)
690
691
@register.inclusion_tag('filer/file_list.html', takes_context=True)
692
def show_user_files(context, folder=None):
693
"""Show files user has access to."""
694
user = context['request'].user
695
696
if folder:
697
files = folder.files.all()
698
else:
699
files = File.objects.all()
700
701
# Filter by permissions
702
accessible_files = [
703
f for f in files
704
if f.has_read_permission(user)
705
]
706
707
return {
708
'files': accessible_files,
709
'user': user,
710
'can_upload': folder.has_add_children_permission(user) if folder else False
711
}
712
```
713
714
### Cache Management
715
716
```python
717
from filer.cache import clear_folder_permission_cache
718
from django.core.management.base import BaseCommand
719
720
class Command(BaseCommand):
721
"""Management command to clear permission cache."""
722
723
def add_arguments(self, parser):
724
parser.add_argument('--user', type=str, help='Clear cache for specific user')
725
726
def handle(self, *args, **options):
727
if options['user']:
728
from django.contrib.auth.models import User
729
user = User.objects.get(username=options['user'])
730
clear_folder_permission_cache(user)
731
self.stdout.write(f"Cleared cache for user: {user.username}")
732
else:
733
clear_folder_permission_cache()
734
self.stdout.write("Cleared all permission caches")
735
736
# Usage: python manage.py clear_filer_cache --user=john
737
```