1
-
2
1
from django import forms
3
2
from django .conf import settings
4
- from django .utils .html import escape
5
- from django .utils .safestring import mark_safe
6
- from django .utils .encoding import force_unicode
7
- from django .contrib .admin .util import flatten_fieldsets
3
+ from django .contrib .admin .util import flatten_fieldsets , lookup_field
4
+ from django .contrib .admin .util import display_for_field , label_for_field
8
5
from django .contrib .contenttypes .models import ContentType
6
+ from django .core .exceptions import ObjectDoesNotExist
7
+ from django .db .models .fields import FieldDoesNotExist
8
+ from django .db .models .fields .related import ManyToManyRel
9
+ from django .forms .util import flatatt
10
+ from django .utils .encoding import force_unicode , smart_unicode
11
+ from django .utils .html import escape , conditional_escape
12
+ from django .utils .safestring import mark_safe
9
13
from django .utils .translation import ugettext_lazy as _
10
14
15
+
11
16
ACTION_CHECKBOX_NAME = '_selected_action'
12
17
13
18
class ActionForm (forms .Form ):
@@ -16,16 +21,24 @@ class ActionForm(forms.Form):
16
21
checkbox = forms .CheckboxInput ({'class' : 'action-select' }, lambda value : False )
17
22
18
23
class AdminForm (object ):
19
- def __init__ (self , form , fieldsets , prepopulated_fields ):
24
+ def __init__ (self , form , fieldsets , prepopulated_fields , readonly_fields = None , model_admin = None ):
20
25
self .form , self .fieldsets = form , normalize_fieldsets (fieldsets )
21
26
self .prepopulated_fields = [{
22
27
'field' : form [field_name ],
23
28
'dependencies' : [form [f ] for f in dependencies ]
24
29
} for field_name , dependencies in prepopulated_fields .items ()]
30
+ self .model_admin = model_admin
31
+ if readonly_fields is None :
32
+ readonly_fields = ()
33
+ self .readonly_fields = readonly_fields
25
34
26
35
def __iter__ (self ):
27
36
for name , options in self .fieldsets :
28
- yield Fieldset (self .form , name , ** options )
37
+ yield Fieldset (self .form , name ,
38
+ readonly_fields = self .readonly_fields ,
39
+ model_admin = self .model_admin ,
40
+ ** options
41
+ )
29
42
30
43
def first_field (self ):
31
44
try :
@@ -49,11 +62,14 @@ def _media(self):
49
62
media = property (_media )
50
63
51
64
class Fieldset (object ):
52
- def __init__ (self , form , name = None , fields = (), classes = (), description = None ):
65
+ def __init__ (self , form , name = None , readonly_fields = (), fields = (), classes = (),
66
+ description = None , model_admin = None ):
53
67
self .form = form
54
68
self .name , self .fields = name , fields
55
69
self .classes = u' ' .join (classes )
56
70
self .description = description
71
+ self .model_admin = model_admin
72
+ self .readonly_fields = readonly_fields
57
73
58
74
def _media (self ):
59
75
if 'collapse' in self .classes :
@@ -63,22 +79,30 @@ def _media(self):
63
79
64
80
def __iter__ (self ):
65
81
for field in self .fields :
66
- yield Fieldline (self .form , field )
82
+ yield Fieldline (self .form , field , self . readonly_fields , model_admin = self . model_admin )
67
83
68
84
class Fieldline (object ):
69
- def __init__ (self , form , field ):
85
+ def __init__ (self , form , field , readonly_fields = None , model_admin = None ):
70
86
self .form = form # A django.forms.Form instance
71
- if isinstance (field , basestring ):
87
+ if not hasattr (field , "__iter__" ):
72
88
self .fields = [field ]
73
89
else :
74
90
self .fields = field
91
+ self .model_admin = model_admin
92
+ if readonly_fields is None :
93
+ readonly_fields = ()
94
+ self .readonly_fields = readonly_fields
75
95
76
96
def __iter__ (self ):
77
97
for i , field in enumerate (self .fields ):
78
- yield AdminField (self .form , field , is_first = (i == 0 ))
98
+ if field in self .readonly_fields :
99
+ yield AdminReadonlyField (self .form , field , is_first = (i == 0 ),
100
+ model_admin = self .model_admin )
101
+ else :
102
+ yield AdminField (self .form , field , is_first = (i == 0 ))
79
103
80
104
def errors (self ):
81
- return mark_safe (u'\n ' .join ([self .form [f ].errors .as_ul () for f in self .fields ]).strip ('\n ' ))
105
+ return mark_safe (u'\n ' .join ([self .form [f ].errors .as_ul () for f in self .fields if f not in self . readonly_fields ]).strip ('\n ' ))
82
106
83
107
class AdminField (object ):
84
108
def __init__ (self , form , field , is_first ):
@@ -100,27 +124,88 @@ def label_tag(self):
100
124
attrs = classes and {'class' : u' ' .join (classes )} or {}
101
125
return self .field .label_tag (contents = contents , attrs = attrs )
102
126
127
+ class AdminReadonlyField (object ):
128
+ def __init__ (self , form , field , is_first , model_admin = None ):
129
+ self .field = field
130
+ self .form = form
131
+ self .model_admin = model_admin
132
+ self .is_first = is_first
133
+ self .is_checkbox = False
134
+ self .is_readonly = True
135
+
136
+ def label_tag (self ):
137
+ attrs = {}
138
+ if not self .is_first :
139
+ attrs ["class" ] = "inline"
140
+ name = forms .forms .pretty_name (
141
+ label_for_field (self .field , self .model_admin .model , self .model_admin )
142
+ )
143
+ contents = force_unicode (escape (name )) + u":"
144
+ return mark_safe ('<label%(attrs)s>%(contents)s</label>' % {
145
+ "attrs" : flatatt (attrs ),
146
+ "contents" : contents ,
147
+ })
148
+
149
+ def contents (self ):
150
+ from django .contrib .admin .templatetags .admin_list import _boolean_icon
151
+ from django .contrib .admin .views .main import EMPTY_CHANGELIST_VALUE
152
+ field , obj , model_admin = self .field , self .form .instance , self .model_admin
153
+ try :
154
+ f , attr , value = lookup_field (field , obj , model_admin )
155
+ except (AttributeError , ObjectDoesNotExist ):
156
+ result_repr = EMPTY_CHANGELIST_VALUE
157
+ else :
158
+ if f is None :
159
+ boolean = getattr (attr , "boolean" , False )
160
+ if boolean :
161
+ result_repr = _boolean_icon (value )
162
+ else :
163
+ result_repr = smart_unicode (value )
164
+ if getattr (attr , "allow_tags" , False ):
165
+ result_repr = mark_safe (result_repr )
166
+ else :
167
+ if value is None :
168
+ result_repr = EMPTY_CHANGELIST_VALUE
169
+ elif isinstance (f .rel , ManyToManyRel ):
170
+ result_repr = ", " .join (map (unicode , value .all ()))
171
+ else :
172
+ result_repr = display_for_field (value , f )
173
+ return conditional_escape (result_repr )
174
+
103
175
class InlineAdminFormSet (object ):
104
176
"""
105
177
A wrapper around an inline formset for use in the admin system.
106
178
"""
107
- def __init__ (self , inline , formset , fieldsets ):
179
+ def __init__ (self , inline , formset , fieldsets , readonly_fields = None , model_admin = None ):
108
180
self .opts = inline
109
181
self .formset = formset
110
182
self .fieldsets = fieldsets
183
+ self .model_admin = model_admin
184
+ if readonly_fields is None :
185
+ readonly_fields = ()
186
+ self .readonly_fields = readonly_fields
111
187
112
188
def __iter__ (self ):
113
189
for form , original in zip (self .formset .initial_forms , self .formset .get_queryset ()):
114
- yield InlineAdminForm (self .formset , form , self .fieldsets , self .opts .prepopulated_fields , original )
190
+ yield InlineAdminForm (self .formset , form , self .fieldsets ,
191
+ self .opts .prepopulated_fields , original , self .readonly_fields ,
192
+ model_admin = self .model_admin )
115
193
for form in self .formset .extra_forms :
116
- yield InlineAdminForm (self .formset , form , self .fieldsets , self .opts .prepopulated_fields , None )
194
+ yield InlineAdminForm (self .formset , form , self .fieldsets ,
195
+ self .opts .prepopulated_fields , None , self .readonly_fields ,
196
+ model_admin = self .model_admin )
117
197
118
198
def fields (self ):
119
199
fk = getattr (self .formset , "fk" , None )
120
- for field_name in flatten_fieldsets (self .fieldsets ):
121
- if fk and fk .name == field_name :
200
+ for i , field in enumerate ( flatten_fieldsets (self .fieldsets ) ):
201
+ if fk and fk .name == field :
122
202
continue
123
- yield self .formset .form .base_fields [field_name ]
203
+ if field in self .readonly_fields :
204
+ label = label_for_field (field , self .opts .model , self .model_admin )
205
+ yield (False , forms .forms .pretty_name (label ))
206
+ else :
207
+ field = self .formset .form .base_fields [field ]
208
+ yield (field .widget .is_hidden , field .label )
124
209
125
210
def _media (self ):
126
211
media = self .opts .media + self .formset .media
@@ -133,17 +218,21 @@ class InlineAdminForm(AdminForm):
133
218
"""
134
219
A wrapper around an inline form for use in the admin system.
135
220
"""
136
- def __init__ (self , formset , form , fieldsets , prepopulated_fields , original ):
221
+ def __init__ (self , formset , form , fieldsets , prepopulated_fields , original ,
222
+ readonly_fields = None , model_admin = None ):
137
223
self .formset = formset
224
+ self .model_admin = model_admin
138
225
self .original = original
139
226
if original is not None :
140
227
self .original_content_type_id = ContentType .objects .get_for_model (original ).pk
141
228
self .show_url = original and hasattr (original , 'get_absolute_url' )
142
- super (InlineAdminForm , self ).__init__ (form , fieldsets , prepopulated_fields )
229
+ super (InlineAdminForm , self ).__init__ (form , fieldsets , prepopulated_fields ,
230
+ readonly_fields )
143
231
144
232
def __iter__ (self ):
145
233
for name , options in self .fieldsets :
146
- yield InlineFieldset (self .formset , self .form , name , ** options )
234
+ yield InlineFieldset (self .formset , self .form , name ,
235
+ self .readonly_fields , model_admin = self .model_admin , ** options )
147
236
148
237
def has_auto_field (self ):
149
238
if self .form ._meta .model ._meta .has_auto_field :
@@ -194,7 +283,8 @@ def __iter__(self):
194
283
for field in self .fields :
195
284
if fk and fk .name == field :
196
285
continue
197
- yield Fieldline (self .form , field )
286
+ yield Fieldline (self .form , field , self .readonly_fields ,
287
+ model_admin = self .model_admin )
198
288
199
289
class AdminErrorList (forms .util .ErrorList ):
200
290
"""
0 commit comments