Ticket #3990: admin_readonly_fields_v1.diff

File admin_readonly_fields_v1.diff, 4.3 KB (added by philippe.raoult@…, 8 years ago)
  • django/newforms/widgets.py

     
    33"""
    44
    55__all__ = (
    6     'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
     6    'Widget', 'DisplayWidget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
    77    'FileInput', 'Textarea', 'CheckboxInput',
    88    'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple',
    99    'MultiWidget', 'SplitDateTimeWidget',
     
    6666        return id_
    6767    id_for_label = classmethod(id_for_label)
    6868
     69class DisplayWidget(Widget):
     70    """
     71    Base class for all read-only pseudo-widgets. Those are used by the admin interface to display read-only values
     72    """
     73    def render(self, name, value, attrs=None):
     74        if value is None:
     75            value = '[Null]'
     76        if value == '':
     77            value = '[Blank]'
     78        return smart_unicode(value)
     79   
     80
    6981class Input(Widget):
    7082    """
    7183    Base class for all <input> widgets (except type='checkbox' and
  • django/contrib/admin/options.py

     
    11from django import oldforms, template
    22from django import newforms as forms
    33from django.contrib.admin import widgets
     4from django.newforms.widgets import DisplayWidget
    45from django.core.exceptions import ImproperlyConfigured, PermissionDenied
    56from django.db import models
    67from django.http import Http404, HttpResponse, HttpResponseRedirect
     
    111112    fields = None
    112113    raw_id_fields = ()
    113114    prepopulated_fields = {}
     115    # this list contains fields that will only be changed when adding an object. They'll only be displayed in change forms
     116    readonly_fields = ()
    114117    filter_vertical = ()
    115118    filter_horizontal = ()
    116119
     
    201204        for fs in self.fieldsets(request):
    202205            yield fs
    203206
    204     def formfield_for_dbfield(self, db_field, **kwargs):
     207    def formfield_for_dbfield_add(self, db_field, override_readonly=True, **kwargs):
    205208        """
     209        call formfield_for_dbfield with override_readonly = True. Used for admin add object forms
     210        """
     211        return self.formfield_for_dbfield(db_field, override_readonly, **kwargs)
     212       
     213    def formfield_for_dbfield(self, db_field, override_readonly=False, **kwargs):
     214        """
    206215        Hook for specifying the form Field instance for a given database Field
    207216        instance.
    208217
    209218        If kwargs are given, they're passed to the form Field's constructor.
    210219        """
     220        # specify that this value cannot be edited by the user. The formfield will decide how to render this.
     221        # The override is used by the create form to set the value.
     222        if not override_readonly and db_field.name in self.readonly_fields:
     223            kwargs['widget'] = DisplayWidget
     224           
    211225        # For ManyToManyFields with a filter interface, use a special Widget.
    212226        if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal):
    213227            kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
     
    392406            # Object list will give 'Permission Denied', so go back to admin home
    393407            post_url = '../../../'
    394408
    395         ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield)
     409        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield_add)
    396410
    397411        if request.POST:
    398412            new_data = request.POST.copy()
     
    443457            new_data = request.POST.copy()
    444458            if opts.has_field_type(models.FileField):
    445459                new_data.update(request.FILES)
     460            # get the values for readonly fields from the object, because they are displayed as strings instead of widgets and thus are not part of the POST request
     461            for fieldname in self.readonly_fields:
     462                fieldvalue = getattr(obj, fieldname)
     463                new_data[fieldname] = fieldvalue
     464               
    446465            form = ModelForm(new_data)
    447466
    448467            if form.is_valid():
Back to Top