aboutsummaryrefslogtreecommitdiffstats
path: root/account/extra.py
blob: 8f034c9072b1ca5d8f1d2cc1bfa0228c66838d2a (plain)
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)