1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# -*- coding: utf-8 -*-
"""
Extra models for app account
"""
from django.db import models
from django import forms
from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
import os
class ContentTypeRestrictedFileField(models.FileField):
"""
Same as FileField, but you can specify:
* content_types - list containing allowed content_types.
Example: ['application/pdf', 'image/jpeg']
* max_upload_size - a number indicating the maximum file
size allowed for upload.
2.5MB - 2621440
5MB - 5242880
10MB - 10485760
20MB - 20971520
50MB - 52428800
100MB - 104857600
250MB - 214958080
500MB - 429916160
"""
def __init__(self, *args, **kwargs):
self.content_types = kwargs.pop("content_types")
self.max_upload_size = kwargs.pop("max_upload_size")
super(ContentTypeRestrictedFileField, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs)
file = data.file
# check content type and file size
try:
content_type = file.content_type
#print content_type
#raise forms.ValidationError(_("Invalid filetype."), code='invalid')
if content_type in self.content_types:
if file._size > self.max_upload_size:
raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(self.max_upload_size), filesizeformat(file._size)), code='invalid')
else:
raise forms.ValidationError(_("Invalid filetype."), code='invalid')
except AttributeError:
pass
#
return data
### OverwriteStorage ###
class OverwriteStorage(FileSystemStorage):
"""
overwrite original file before store the new one
"""
def get_available_name(self, name):
"""
Returns a filename that's free on the target storage system,
and available for new content to be written to.
Ref: http://djangosnippets.org/snippets/976/
This file storage solves overwrite on upload problem. Another
proposed solution was to override the save method on the model
like so (from https://code.djangoproject.com/ticket/11663):
def save(self, *args, **kwargs):
try:
this = MyModelName.objects.get(id=self.id)
if this.MyImageFieldName != self.MyImageFieldName:
this.MyImageFieldName.delete()
except: pass
super(MyModelName, self).save(*args, **kwargs)
"""
# If the filename already exists,
# remove it as if it was a true file system
if self.exists(name):
filepath = os.path.join(settings.MEDIA_ROOT, name)
if os.path.isfile(filepath):
os.remove(filepath)
return name
### delete files associated with model FileField
# Pre-delete signal function for deleting files a model
# https://djangosnippets.org/snippets/2820/
def file_cleanup(sender, instance, *args, **kwargs):
"""
Deletes the file(s) associated with a model instance. The model
is not saved after deletion of the file(s) since this is meant
to be used with the pre_delete signal.
"""
for field_name, _ in instance.__dict__.iteritems():
field = getattr(instance, field_name)
if (issubclass(field.__class__, FieldFile) and field.name):
# pass False so FileField does not save the model
field.delete(save=False)
|