Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 271 lines (231 sloc) 10.944 kb
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
1 """
2 Form Widget classes specific to the Django admin site.
3 """
4
5 import copy
6
46786b41 » jacobian
2008-07-19 Fixed #7741: django.newforms is now django.forms. This is obviously a…
7 from django import forms
8 from django.forms.widgets import RadioFieldRenderer
9 from django.forms.util import flatatt
29f0e818 » adrianholovaty
2008-07-22 Fixed #7847 -- Removed a whole bunch of unused imports from throughou…
10 from django.utils.text import truncate_words
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
11 from django.utils.translation import ugettext as _
12 from django.utils.safestring import mark_safe
13 from django.utils.encoding import force_unicode
14 from django.conf import settings
15
16 class FilteredSelectMultiple(forms.SelectMultiple):
17 """
18 A SelectMultiple with a JavaScript filter interface.
19
d05ebdb6 » brosner
2008-08-31 Fixed #8058 -- Moved media for filter_vertical/filter_horizontal widg…
20 Note that the resulting JavaScript assumes that the jsi18n
21 catalog has been loaded in the page
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
22 """
d05ebdb6 » brosner
2008-08-31 Fixed #8058 -- Moved media for filter_vertical/filter_horizontal widg…
23 class Media:
24 js = (settings.ADMIN_MEDIA_PREFIX + "js/core.js",
25 settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",
26 settings.ADMIN_MEDIA_PREFIX + "js/SelectFilter2.js")
27
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
28 def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
29 self.verbose_name = verbose_name
30 self.is_stacked = is_stacked
31 super(FilteredSelectMultiple, self).__init__(attrs, choices)
32
33 def render(self, name, value, attrs=None, choices=()):
34 output = [super(FilteredSelectMultiple, self).render(name, value, attrs, choices)]
35 output.append(u'<script type="text/javascript">addEvent(window, "load", function(e) {')
36 # TODO: "id_" is hard-coded here. This should instead use the correct
37 # API to determine the ID dynamically.
38 output.append(u'SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % \
39 (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX))
40 return mark_safe(u''.join(output))
41
42 class AdminDateWidget(forms.TextInput):
43 class Media:
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
44 js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
45 settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
46
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
47 def __init__(self, attrs={}):
48 super(AdminDateWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'})
49
50 class AdminTimeWidget(forms.TextInput):
51 class Media:
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
52 js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
53 settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
54
55 def __init__(self, attrs={}):
56 super(AdminTimeWidget, self).__init__(attrs={'class': 'vTimeField', 'size': '8'})
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
57
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
58 class AdminSplitDateTime(forms.SplitDateTimeWidget):
59 """
60 A SplitDateTime Widget that has some admin-specific styling.
61 """
62 def __init__(self, attrs=None):
63 widgets = [AdminDateWidget, AdminTimeWidget]
64 # Note that we're calling MultiWidget, not SplitDateTimeWidget, because
65 # we want to define widgets.
66 forms.MultiWidget.__init__(self, widgets, attrs)
67
68 def format_output(self, rendered_widgets):
69 return mark_safe(u'<p class="datetime">%s %s<br />%s %s</p>' % \
70 (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
71
72 class AdminRadioFieldRenderer(RadioFieldRenderer):
73 def render(self):
74 """Outputs a <ul> for this set of radio fields."""
75 return mark_safe(u'<ul%s>\n%s\n</ul>' % (
76 flatatt(self.attrs),
77 u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self]))
78 )
79
80 class AdminRadioSelect(forms.RadioSelect):
81 renderer = AdminRadioFieldRenderer
82
83 class AdminFileWidget(forms.FileInput):
84 """
85 A FileField Widget that shows its current value if it has one.
86 """
87 def __init__(self, attrs={}):
88 super(AdminFileWidget, self).__init__(attrs)
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
89
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
90 def render(self, name, value, attrs=None):
91 output = []
38dc4727 » brosner
2008-08-10 Fixed #7250 -- Don't show internal data of a FileField in the admin w…
92 if value and hasattr(value, "url"):
7899568e » jacobian
2008-08-08 File storage refactoring, adding far more flexibility to Django's fil…
93 output.append('%s <a target="_blank" href="%s">%s</a> <br />%s ' % \
94 (_('Currently:'), value.url, value, _('Change:')))
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
95 output.append(super(AdminFileWidget, self).render(name, value, attrs))
96 return mark_safe(u''.join(output))
97
98 class ForeignKeyRawIdWidget(forms.TextInput):
99 """
100 A Widget for displaying ForeignKeys in the "raw_id" interface rather than
101 in a <select> box.
102 """
103 def __init__(self, rel, attrs=None):
104 self.rel = rel
105 super(ForeignKeyRawIdWidget, self).__init__(attrs)
106
107 def render(self, name, value, attrs=None):
108 related_url = '../../../%s/%s/' % (self.rel.to._meta.app_label, self.rel.to._meta.object_name.lower())
0cd5caa6 » brosner
2008-09-02 Fixed #8787 -- Fixed failing admin_widgets tests. This fixes ManyToMa…
109 params = self.url_parameters()
110 if params:
111 url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in params.items()])
112 else:
113 url = ''
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
114 if not attrs.has_key('class'):
115 attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript looks for this hook.
116 output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)]
117 # TODO: "id_" is hard-coded here. This should instead use the correct
118 # API to determine the ID dynamically.
119 output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \
120 (related_url, url, name))
0c66bac4 » jacobian
2008-08-28 Marked a handful of missed strings for translation. Fixes #8644, #861…
121 output.append('<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="%s" /></a>' % (settings.ADMIN_MEDIA_PREFIX, _('Lookup')))
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
122 if value:
123 output.append(self.label_for_value(value))
124 return mark_safe(u''.join(output))
0cd5caa6 » brosner
2008-09-02 Fixed #8787 -- Fixed failing admin_widgets tests. This fixes ManyToMa…
125
126 def base_url_parameters(self):
127 params = {}
128 if self.rel.limit_choices_to:
129 params.update(dict([(k, ','.join(v)) for k, v in self.rel.limit_choices_to.items()]))
130 return params
131
132 def url_parameters(self):
133 from django.contrib.admin.views.main import TO_FIELD_VAR
134 params = self.base_url_parameters()
135 params.update({TO_FIELD_VAR: self.rel.get_related_field().name})
136 return params
137
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
138 def label_for_value(self, value):
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
139 key = self.rel.get_related_field().name
140 obj = self.rel.to.objects.get(**{key: value})
141 return '&nbsp;<strong>%s</strong>' % truncate_words(obj, 14)
142
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
143 class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
144 """
145 A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
146 in a <select multiple> box.
147 """
148 def __init__(self, rel, attrs=None):
149 super(ManyToManyRawIdWidget, self).__init__(rel, attrs)
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
150
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
151 def render(self, name, value, attrs=None):
152 attrs['class'] = 'vManyToManyRawIdAdminField'
153 if value:
154 value = ','.join([str(v) for v in value])
155 else:
156 value = ''
157 return super(ManyToManyRawIdWidget, self).render(name, value, attrs)
0cd5caa6 » brosner
2008-09-02 Fixed #8787 -- Fixed failing admin_widgets tests. This fixes ManyToMa…
158
159 def url_parameters(self):
160 return self.base_url_parameters()
161
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
162 def label_for_value(self, value):
163 return ''
164
165 def value_from_datadict(self, data, files, name):
166 value = data.get(name, None)
167 if value and ',' in value:
168 return data[name].split(',')
169 if value:
170 return [value]
171 return None
ce47d4ab » brosner
2008-09-01 Fixed #8648 -- Admin no longer ignores to_field. Thanks for the help …
172
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
173 def _has_changed(self, initial, data):
174 if initial is None:
175 initial = []
176 if data is None:
177 data = []
178 if len(initial) != len(data):
179 return True
180 for pk1, pk2 in zip(initial, data):
181 if force_unicode(pk1) != force_unicode(pk2):
182 return True
183 return False
184
185 class RelatedFieldWidgetWrapper(forms.Widget):
186 """
187 This class is a wrapper to a given widget to add the add icon for the
188 admin interface.
189 """
190 def __init__(self, widget, rel, admin_site):
191 self.is_hidden = widget.is_hidden
192 self.needs_multipart_form = widget.needs_multipart_form
193 self.attrs = widget.attrs
194 self.choices = widget.choices
195 self.widget = widget
196 self.rel = rel
197 # so we can check if the related object is registered with this AdminSite
198 self.admin_site = admin_site
199
200 def __deepcopy__(self, memo):
201 obj = copy.copy(self)
202 obj.widget = copy.deepcopy(self.widget, memo)
203 obj.attrs = self.widget.attrs
204 memo[id(self)] = obj
205 return obj
206
d05ebdb6 » brosner
2008-08-31 Fixed #8058 -- Moved media for filter_vertical/filter_horizontal widg…
207 def _media(self):
208 return self.widget.media
209 media = property(_media)
210
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
211 def render(self, name, value, *args, **kwargs):
212 rel_to = self.rel.to
213 related_url = '../../../%s/%s/' % (rel_to._meta.app_label, rel_to._meta.object_name.lower())
214 self.widget.choices = self.choices
215 output = [self.widget.render(name, value, *args, **kwargs)]
216 if rel_to in self.admin_site._registry: # If the related object has an admin interface:
217 # TODO: "id_" is hard-coded here. This should instead use the correct
218 # API to determine the ID dynamically.
219 output.append(u'<a href="%sadd/" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
220 (related_url, name))
0c66bac4 » jacobian
2008-08-28 Marked a handful of missed strings for translation. Fixes #8644, #861…
221 output.append(u'<img src="%simg/admin/icon_addlink.gif" width="10" height="10" alt="%s"/></a>' % (settings.ADMIN_MEDIA_PREFIX, _('Add Another')))
a19ed8ae » brosner
2008-07-18 Merged the newforms-admin branch into trunk.
222 return mark_safe(u''.join(output))
223
224 def build_attrs(self, extra_attrs=None, **kwargs):
225 "Helper function for building an attribute dictionary."
226 self.attrs = self.widget.build_attrs(extra_attrs=None, **kwargs)
227 return self.attrs
228
229 def value_from_datadict(self, data, files, name):
230 return self.widget.value_from_datadict(data, files, name)
231
232 def _has_changed(self, initial, data):
233 return self.widget._has_changed(initial, data)
234
235 def id_for_label(self, id_):
236 return self.widget.id_for_label(id_)
5d199ba9 » brosner
2008-08-08 Fixed #8163 -- Restore oldforms admin styling on input fields. Also c…
237
238 class AdminTextareaWidget(forms.Textarea):
1c9ca83d » brosner
2008-08-08 Fixed #8169 -- Honor attrs from subclasses of the new admin widgets i…
239 def __init__(self, attrs=None):
240 final_attrs = {'class': 'vLargeTextField'}
241 if attrs is not None:
242 final_attrs.update(attrs)
84afcf5a » brosner
2008-08-08 Removed an extraneous } that regressed from an older patch for [8247].
243 super(AdminTextareaWidget, self).__init__(attrs=final_attrs)
5d199ba9 » brosner
2008-08-08 Fixed #8163 -- Restore oldforms admin styling on input fields. Also c…
244
245 class AdminTextInputWidget(forms.TextInput):
1c9ca83d » brosner
2008-08-08 Fixed #8169 -- Honor attrs from subclasses of the new admin widgets i…
246 def __init__(self, attrs=None):
247 final_attrs = {'class': 'vTextField'}
248 if attrs is not None:
249 final_attrs.update(attrs)
250 super(AdminTextInputWidget, self).__init__(attrs=final_attrs)
5d199ba9 » brosner
2008-08-08 Fixed #8163 -- Restore oldforms admin styling on input fields. Also c…
251
252 class AdminURLFieldWidget(forms.TextInput):
1c9ca83d » brosner
2008-08-08 Fixed #8169 -- Honor attrs from subclasses of the new admin widgets i…
253 def __init__(self, attrs=None):
254 final_attrs = {'class': 'vURLField'}
255 if attrs is not None:
256 final_attrs.update(attrs)
257 super(AdminURLFieldWidget, self).__init__(attrs=final_attrs)
5d199ba9 » brosner
2008-08-08 Fixed #8163 -- Restore oldforms admin styling on input fields. Also c…
258
259 class AdminIntegerFieldWidget(forms.TextInput):
1c9ca83d » brosner
2008-08-08 Fixed #8169 -- Honor attrs from subclasses of the new admin widgets i…
260 def __init__(self, attrs=None):
261 final_attrs = {'class': 'vIntegerField'}
262 if attrs is not None:
263 final_attrs.update(attrs)
264 super(AdminIntegerFieldWidget, self).__init__(attrs=final_attrs)
a41ca9c9 » jacobian
2008-08-28 Fixed #8556: added a useful formfield to `CommaSeparatedIntegerField`…
265
266 class AdminCommaSeparatedIntegerFieldWidget(forms.TextInput):
267 def __init__(self, attrs=None):
268 final_attrs = {'class': 'vCommaSeparatedIntegerField'}
269 if attrs is not None:
270 final_attrs.update(attrs)
271 super(AdminCommaSeparatedIntegerFieldWidget, self).__init__(attrs=final_attrs)
Something went wrong with that request. Please try again.