Ticket #3990: admin_readonly_fields_v1.patch

File admin_readonly_fields_v1.patch, 3.6 KB (added by philippe.raoult, 8 years ago)
  • django/newforms/widgets.py

     
    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

     
    111111    fields = None
    112112    raw_id_fields = ()
    113113    prepopulated_fields = {}
     114    # this list contains fields that will only be changed when adding an object. They'll only be displayed in change forms
     115    readonly_fields = ()
    114116    filter_vertical = ()
    115117    filter_horizontal = ()
    116118
     
    201203        for fs in self.fieldsets(request):
    202204            yield fs
    203205
    204     def formfield_for_dbfield(self, db_field, **kwargs):
     206    def formfield_for_dbfield_add(self, db_field, override_readonly=True, **kwargs):
    205207        """
     208        call formfield_for_dbfield with override_readonly = True. Used for admin add object forms
     209        """
     210        return self.formfield_for_dbfield(db_field, override_readonly, **kwargs)
     211       
     212    def formfield_for_dbfield(self, db_field, override_readonly=False, **kwargs):
     213        """
    206214        Hook for specifying the form Field instance for a given database Field
    207215        instance.
    208216
    209217        If kwargs are given, they're passed to the form Field's constructor.
    210218        """
     219        # specify that this value cannot be edited by the user. The formfield will decide how to render this.
     220        # The override is used by the create form to set the value.
     221        if not override_readonly and db_field.name in self.readonly_fields:
     222            kwargs['widget'] = DisplayWidget
     223#            kwargs['readonly'] = True
     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