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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 | import os, urllib, urllib2, mimetypes
from urlparse import urlparse
from django.forms.widgets import FileInput, CheckboxInput, TextInput
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files.temp import NamedTemporaryFile
from django.utils.html import escape, conditional_escape
from django.utils.translation import ugettext, ugettext_lazy
from django.utils.encoding import StrAndUnicode, force_unicode
from django.utils.safestring import mark_safe
FILE_INPUT_CONTRADICTION = object()
class URLFileInput(FileInput):
initial_text = ugettext_lazy('Currently')
input_text = ugettext_lazy('Change')
clear_checkbox_label = ugettext_lazy('Clear')
url_text_label = ugettext_lazy('From URL')
template_with_initial = u'<p class="file-upload">%(initial_text)s: %(initial)s %(clear_template)s<br />%(url_template)s<br />%(input_text)s: %(input)s</p>'
template_only_url = u'<p class="file-upload">%(url_template)s<br />%(input_text)s: %(input)s</p>'
template_with_clear = u'<span class="clearable-file-input">%(clear)s <label for="%(clear_checkbox_id)s">%(clear_checkbox_label)s</label></span>'
template_with_url = u'%(url_text_label)s: %(url)s'
def clear_checkbox_name(self, name):
"""
Given the name of the file input, return the name of the clear checkbox
input.
"""
return name + '-clear'
def clear_checkbox_id(self, name):
"""
Given the name of the clear checkbox input, return the HTML id for it.
"""
return name + '_id'
def url_text_name(self, name):
"""
Given the name of the file input, return the name of the url text
input.
"""
return name + '-url-clear'
def url_text_id(self, name):
"""
Given the name of the url text input, return the HTML id for it.
"""
return name + '_url_id'
def render(self, name, value, attrs=None):
substitutions = {
'initial_text': self.initial_text,
'input_text': self.input_text,
'clear_template': '',
'clear_checkbox_label': self.clear_checkbox_label,
'url_text_label': self.url_text_label,
}
template = self.template_only_url
substitutions['input'] = super(URLFileInput, self).render(name, value, attrs)
if value and hasattr(value, "url"):
template = self.template_with_initial
substitutions['initial'] = (u'<a href="%s">%s</a>'
% (escape(value.url),
escape(force_unicode(value))))
if not self.is_required:
checkbox_name = self.clear_checkbox_name(name)
checkbox_id = self.clear_checkbox_id(checkbox_name)
substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
substitutions['clear_template'] = self.template_with_clear % substitutions
text_name = self.url_text_name(name)
text_id = self.url_text_id(text_name)
substitutions['url_text_name'] = conditional_escape(text_name)
substitutions['url_text_id'] = conditional_escape(text_id)
substitutions['url'] = TextInput().render(text_name, "", attrs={'id': text_id, "style":"width:400px"})
substitutions['url_template'] = self.template_with_url % substitutions
return mark_safe(template % substitutions)
def value_from_datadict(self, data, files, name):
upload = super(URLFileInput, self).value_from_datadict(data, files, name)
if not self.is_required and CheckboxInput().value_from_datadict(
data, files, self.clear_checkbox_name(name)):
if upload:
# If the user contradicts themselves (uploads a new file AND
# checks the "clear" checkbox), we return a unique marker
# object that FileField will turn into a ValidationError.
return FILE_INPUT_CONTRADICTION
# False signals to clear any existing value, as opposed to just None
return False
url = TextInput().value_from_datadict(data, files,
self.url_text_name(name))
if url:
validate = URLValidator(verify_exists=False)
try:
validate(url)
except ValidationError, e:
url = None
parsed_url = urlparse(url)
name = os.path.basename(parsed_url[2])
ext = os.path.splitext(parsed_url[2])[1]
if url and ext in [".png", ".gif", ".jpg"]:
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
ze_file = opener.open(url).read()
upload = SimpleUploadedFile(name=name, content=ze_file, content_type=mimetypes.guess_type(name))
return upload
|
Comments
Thanks. This is really useful, however the description mentions a
default_extsargument which does not appear to be used anywhere. Conversely, the extensions accepted are hardcoded:#