Changeset 7771
- Timestamp:
- 06/26/08 11:53:53 (1 year ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/newforms-admin/django/contrib/admin/options.py
r7638 r7771 199 199 # Don't wrap raw_id fields. Their add function is in the popup window. 200 200 if not db_field.name in self.raw_id_fields: 201 formfield.widget .render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel, self.admin_site)201 formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site) 202 202 return formfield 203 203 django/branches/newforms-admin/django/contrib/admin/widgets.py
r7626 r7771 2 2 Form Widget classes specific to the Django admin site. 3 3 """ 4 5 import copy 4 6 5 7 from django import newforms as forms … … 163 165 return False 164 166 165 class RelatedFieldWidgetWrapper(object): 166 """ 167 This class is a wrapper whose __call__() method mimics the interface of a 168 Widget's render() method. 169 """ 170 def __init__(self, render_func, rel, admin_site): 171 self.render_func, self.rel = render_func, rel 167 class RelatedFieldWidgetWrapper(forms.Widget): 168 """ 169 This class is a wrapper to a given widget to add the add icon for the 170 admin interface. 171 """ 172 def __init__(self, widget, rel, admin_site): 173 self.is_hidden = widget.is_hidden 174 self.needs_multipart_form = widget.needs_multipart_form 175 self.attrs = widget.attrs 176 self.choices = widget.choices 177 self.widget = widget 178 self.rel = rel 172 179 # so we can check if the related object is registered with this AdminSite 173 180 self.admin_site = admin_site 174 181 175 def __call__(self, name, value, *args, **kwargs): 182 def __deepcopy__(self, memo): 183 obj = copy.copy(self) 184 obj.widget = copy.deepcopy(self.widget, memo) 185 obj.attrs = self.widget.attrs 186 memo[id(self)] = obj 187 return obj 188 189 def render(self, name, value, *args, **kwargs): 176 190 from django.conf import settings 177 191 rel_to = self.rel.to 178 192 related_url = '../../../%s/%s/' % (rel_to._meta.app_label, rel_to._meta.object_name.lower()) 179 output = [self.render_func(name, value, *args, **kwargs)] 193 self.widget.choices = self.choices 194 output = [self.widget.render(name, value, *args, **kwargs)] 180 195 if rel_to in self.admin_site._registry: # If the related object has an admin interface: 181 196 # TODO: "id_" is hard-coded here. This should instead use the correct … … 186 201 return mark_safe(u''.join(output)) 187 202 188 def __deepcopy__(self, memo): 189 # There's no reason to deepcopy admin_site, etc, so just return self. 190 memo[id(self)] = self 191 return self 203 def build_attrs(self, extra_attrs=None, **kwargs): 204 "Helper function for building an attribute dictionary." 205 self.attrs = self.widget.build_attrs(extra_attrs=None, **kwargs) 206 return self.attrs 207 208 def value_from_datadict(self, data, files, name): 209 return self.widget.value_from_datadict(data, files, name) 210 211 def _has_changed(self, initial, data): 212 return self.widget._has_changed(initial, data) 213 214 def id_for_label(self, id_): 215 return self.widget.id_for_label(id_) django/branches/newforms-admin/tests/regressiontests/modeladmin/models.py
r7626 r7771 123 123 <class 'django.contrib.admin.widgets.AdminDateWidget'> 124 124 125 If we need to override the queryset of a ModelChoiceField in our custom form 126 make sure that RelatedFieldWidgetWrapper doesn't mess that up. 127 128 >>> band2 = Band(name='The Beetles', bio='', sign_date=date(1962, 1, 1)) 129 >>> band2.save() 130 131 >>> class AdminConcertForm(forms.ModelForm): 132 ... class Meta: 133 ... model = Concert 134 ... 135 ... def __init__(self, *args, **kwargs): 136 ... super(AdminConcertForm, self).__init__(*args, **kwargs) 137 ... self.fields["main_band"].queryset = Band.objects.filter(name='The Doors') 138 139 >>> class ConcertAdmin(ModelAdmin): 140 ... form = AdminConcertForm 141 142 >>> ma = ConcertAdmin(Concert, site) 143 >>> form = ma.get_form(request)() 144 >>> print form["main_band"] 145 <select name="main_band" id="id_main_band"> 146 <option value="" selected="selected">---------</option> 147 <option value="1">The Doors</option> 148 </select> 149 150 >>> band2.delete() 151 125 152 # radio_fields behavior ################################################ 126 153 127 154 First, without any radio_fields specified, the widgets for ForeignKey 128 155 and fields with choices specified ought to be a basic Select widget. 129 For Select fields, all of the choices lists have a first entry of dashes. 156 ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so 157 they need to be handled properly when type checking. For Select fields, all of 158 the choices lists have a first entry of dashes. 130 159 131 160 >>> cma = ModelAdmin(Concert, site) 132 161 >>> cmafa = cma.get_form(request) 133 162 134 >>> type(cmafa.base_fields['main_band'].widget )163 >>> type(cmafa.base_fields['main_band'].widget.widget) 135 164 <class 'django.newforms.widgets.Select'> 136 165 >>> list(cmafa.base_fields['main_band'].widget.choices) 137 166 [(u'', u'---------'), (1, u'The Doors')] 138 167 139 >>> type(cmafa.base_fields['opening_band'].widget )168 >>> type(cmafa.base_fields['opening_band'].widget.widget) 140 169 <class 'django.newforms.widgets.Select'> 141 170 >>> list(cmafa.base_fields['opening_band'].widget.choices) … … 153 182 154 183 Now specify all the fields as radio_fields. Widgets should now be 155 RadioSelect, and the choices list should have a first entry of 'None' if f184 RadioSelect, and the choices list should have a first entry of 'None' if 156 185 blank=True for the model field. Finally, the widget should have the 157 186 'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL. … … 168 197 >>> cmafa = cma.get_form(request) 169 198 170 >>> type(cmafa.base_fields['main_band'].widget )199 >>> type(cmafa.base_fields['main_band'].widget.widget) 171 200 <class 'django.contrib.admin.widgets.AdminRadioSelect'> 172 201 >>> cmafa.base_fields['main_band'].widget.attrs … … 175 204 [(1, u'The Doors')] 176 205 177 >>> type(cmafa.base_fields['opening_band'].widget )206 >>> type(cmafa.base_fields['opening_band'].widget.widget) 178 207 <class 'django.contrib.admin.widgets.AdminRadioSelect'> 179 208 >>> cmafa.base_fields['opening_band'].widget.attrs
