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
105
|
# -*- coding: utf-8 -*-
"""
Extra models for app account
"""
from django import forms
from django.db import models
from django.db.models.fields.files import FieldFile
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 %(maxsize)s. Current filesize %(filesize)s') % {'maxsize':filesizeformat(self.max_upload_size), 'filesize':filesizeformat(file._size)}, code='invalid')
else:
raise forms.ValidationError(_("Unsupported 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)
|