forked from django-cms/django-filer
/
file.py
141 lines (123 loc) · 4.99 KB
/
file.py
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import logging
import warnings
from django import forms
from django.conf import settings
from django.contrib.admin.sites import site
from django.contrib.admin.widgets import ForeignKeyRawIdWidget
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
from .. import settings as filer_settings
from ..models import File
from ..utils.compatibility import truncate_words
from ..utils.model_label import get_model_label
logger = logging.getLogger(__name__)
class AdminFileWidget(ForeignKeyRawIdWidget):
choices = None
def render(self, name, value, attrs=None, renderer=None):
obj = self.obj_for_value(value)
css_id = attrs.get('id', 'id_image_x')
related_url = None
change_url = ''
if value:
try:
file_obj = File.objects.get(pk=value)
related_url = file_obj.logical_folder.get_admin_directory_listing_url_path()
change_url = file_obj.get_admin_change_url()
except Exception as e:
# catch exception and manage it. We can re-raise it for debugging
# purposes and/or just logging it, provided user configured
# proper logging configuration
if filer_settings.FILER_ENABLE_LOGGING:
logger.error('Error while rendering file widget: %s', e)
if filer_settings.FILER_DEBUG:
raise
if not related_url:
related_url = reverse('admin:filer-directory_listing-last')
params = self.url_parameters()
params['_pick'] = 'file'
if params:
lookup_url = '?' + urlencode(sorted(params.items()))
else:
lookup_url = ''
if 'class' not in attrs:
# The JavaScript looks for this hook.
attrs['class'] = 'vForeignKeyRawIdAdminField'
# rendering the super for ForeignKeyRawIdWidget on purpose here because
# we only need the input and none of the other stuff that
# ForeignKeyRawIdWidget adds
hidden_input = super(ForeignKeyRawIdWidget, self).render(name, value, attrs) # grandparent super
context = {
'hidden_input': hidden_input,
'lookup_url': '%s%s' % (related_url, lookup_url),
'change_url': change_url,
'object': obj,
'lookup_name': name,
'id': css_id,
'admin_icon_delete': ('admin/img/icon-deletelink.svg'),
}
html = render_to_string('admin/filer/widgets/admin_file.html', context)
return mark_safe(html)
def label_for_value(self, value):
obj = self.obj_for_value(value)
return ' <strong>%s</strong>' % truncate_words(obj, 14)
def obj_for_value(self, value):
if value:
try:
# the next line may never bee reached
key = self.rel.get_related_field().name
obj = self.rel.model._default_manager.get(**{key: value})
except ObjectDoesNotExist:
obj = None
else:
obj = None
return obj
class Media:
extra = '' if settings.DEBUG else '.min'
css = {
'all': [
'filer/css/admin_filer.css',
]
}
js = (
'admin/js/vendor/jquery/jquery%s.js' % extra,
'admin/js/jquery.init.js',
'filer/js/libs/dropzone.min.js',
'filer/js/addons/dropzone.init.js',
'filer/js/addons/popup_handling.js',
'filer/js/addons/widget.js',
)
class AdminFileFormField(forms.ModelChoiceField):
widget = AdminFileWidget
def __init__(self, rel, queryset, to_field_name, *args, **kwargs):
self.rel = rel
self.queryset = queryset
self.to_field_name = to_field_name
self.max_value = None
self.min_value = None
kwargs.pop('widget', None)
super().__init__(queryset, widget=self.widget(rel, site), *args, **kwargs)
def widget_attrs(self, widget):
widget.required = self.required
return {}
class FilerFileField(models.ForeignKey):
default_form_class = AdminFileFormField
default_model_class = File
def __init__(self, **kwargs):
to = kwargs.pop('to', None)
dfl = get_model_label(self.default_model_class)
if to and get_model_label(to).lower() != dfl.lower():
msg = "In {}: ForeignKey must point to {}; instead passed {}"
warnings.warn(msg.format(self.__class__.__name__, dfl, to), SyntaxWarning)
kwargs['to'] = dfl # hard-code `to` to model `filer.File`
super().__init__(**kwargs)
def formfield(self, **kwargs):
defaults = {
'form_class': self.default_form_class,
'rel': self.remote_field,
}
defaults.update(kwargs)
return super().formfield(**defaults)