Opened 5 years ago

Closed 2 years ago

#14802 closed New feature (wontfix)

feature request: add a method to Fields that is used to render the field as read-only

Reported by: nickname123 Owned by: cogat
Component: contrib.admin Version: 1.2
Severity: Normal Keywords: sprintdec2010 hidden_widget
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: yes

Description

It is possible to override the default widget that is used to render a custom model field... however the hidden_widget is more difficult. The only way appears to be on a per model basis by changing the widget in the model admin. This can be very difficult/impractical when inheriting models that make use of the custom field with the field set to readonly in the model admin.

For example, a simple field that uses a custom widget:

class CustomFileWidget(forms.FileInput):
	return mark_safe(u"CustomFileWidget was used: %s" % super(CustomFileWidget, self).render(name, value, attrs))
	
class CustomFileFormField(forms.FileField):
    def __init__(self, *args, **kwargs):
        kwargs['widget'] = CustomFileWidget
        super(CustomFileFormField, self).__init__(*args, **kwargs)
        
class CustomFileField(models.FileField):
    def formfield(self, **kwargs):
        return super(CustomFileField, self).formfield(form_class=CustomFileFormField,**kwargs)



However, there does not appear to be a kwarg for hidden_widget and using something like the following will not work:

class CustomFileFormField(forms.FileField):
    hidden_widget = CustomFileWidget
    widget = CustomFileWidget
class CustomFileField(models.FileField):
    def formfield(self, **kwargs):
        return super(CustomFileField, self).formfield(form_class=CustomFileFormField,**kwargs)

Change History (15)

comment:1 follow-up: Changed 5 years ago by cogat

  • Keywords sprintdec2010 added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed
  • Triage Stage changed from Unreviewed to Design decision needed

The admin app doesn't render hidden_widget at all, it just displays readonly fields (using getattr(modelinstance, fieldname)). AFAICS hidden_widget is only used by form previews and form wizards for holding on to copies of fields that were entered in an earlier view.

If you are asking for a customised way to render a read-only field, then it might be helpful to know that you can pass a callable to readonly_fields that renders the result you want.

class Song(models.Model):
    band = models.ForeignKey(Band)
    title = CustomModelField(max_length=100)
    
    def rendertitle(self):
        return "A custom rendering of %s" % self.title

class SongAdmin(admin.ModelAdmin):
    exclude = ('title',)
    readonly_fields = ('rendertitle', )

comment:2 in reply to: ↑ 1 ; follow-up: Changed 5 years ago by nickname123

  • Resolution wontfix deleted
  • Status changed from closed to reopened

Replying to cogat:

The admin app doesn't render hidden_widget at all, it just displays readonly fields (using getattr(modelinstance, fieldname)). AFAICS hidden_widget is only used by form previews and form wizards for holding on to copies of fields that were entered in an earlier view.

If you are asking for a customised way to render a read-only field, then it might be helpful to know that you can pass a callable to readonly_fields that renders the result you want.

class Song(models.Model):
    band = models.ForeignKey(Band)
    title = CustomModelField(max_length=100)
    
    def rendertitle(self):
        return "A custom rendering of %s" % self.title

class SongAdmin(admin.ModelAdmin):
    exclude = ('title',)
    readonly_fields = ('rendertitle', )

Wouldn't it be a better idea (in the future) to use a widget to render the readonly value so that the default appearance can be overridden? Using a field like that may be nice in some situations, but it doesn't work well for my use case.

I don't think it would work well with any abstract model that is used repeatedly because you have to remember to add the callable to readonly_fields in every model's admin entry that inherits it. And also for admin inlines.

comment:3 in reply to: ↑ 2 ; follow-up: Changed 5 years ago by cogat

  • milestone 1.3 deleted

Just to clarify, a widget in Django is its representation of an HTML input element, so it doesn't make sense to use it for anything that doesn't involve displaying and handling an input element. So for read-only fields there's no need to use a widget.

Given this, I think you're asking for each Field to have a method that is called by admin that renders the field as a read-only HTML. That's something I could get behind (it's better to attach field display to fields than to models, and there are currently silly special-cases for rendering BooleanFields as icons in the current code) but it needs a design decision. Particularly, would the same method, or a variation on it, be used to render the field in admin list views? What about mechanisms for requiring external javascript/css files needed by the rendering? What about specifying read-only fields (so the same method can be used) in non-admin forms?

However, without a patch this won't make it into 1.3, so I'll remove the milestone.

comment:4 Changed 5 years ago by cogat

  • Summary changed from feature request: ability to override default hidden_widget used to render a custom model field when marked as readonly in the admin to feature request: add a method to Fields that is used when rendering as readonly

comment:5 Changed 5 years ago by cogat

  • Summary changed from feature request: add a method to Fields that is used when rendering as readonly to feature request: add a method to Fields that is used to render the field as read-only

comment:6 follow-up: Changed 5 years ago by cogat

  • Owner changed from nobody to cogat
  • Status changed from reopened to new

I'll have a crack at this.

comment:7 in reply to: ↑ 3 Changed 5 years ago by nickname123

Replying to cogat:

Just to clarify, a widget in Django is its representation of an HTML input element, so it doesn't make sense to use it for anything that doesn't involve displaying and handling an input element. So for read-only fields there's no need to use a widget.

Given this, I think you're asking for each Field to have a method that is called by admin that renders the field as a read-only HTML. That's something I could get behind (it's better to attach field display to fields than to models, and there are currently silly special-cases for rendering BooleanFields as icons in the current code) but it needs a design decision. Particularly, would the same method, or a variation on it, be used to render the field in admin list views? What about mechanisms for requiring external javascript/css files needed by the rendering? What about specifying read-only fields (so the same method can be used) in non-admin forms?

However, without a patch this won't make it into 1.3, so I'll remove the milestone.


In regards to your comment about widgets being the wrong term... the html input tag does have a readonly attribute (http://www.w3schools.com/tags/att_input_readonly.asp). I was talking about using this since widgets are the current way of displaying form fields that are not readonly. This seemed to be the "correct" way to do it.

However, I did not put much thought into how it would be best achieved because I was not sure if the feature had been left out of Django on purpose.

A "to html" method might be a better idea, but I am still in favor using a widget. I think a widget gives a little more abstraction and fits better with the current design. Using a widget opposed to a method on the model would have the benefit of being easily overridden too. I think it is a nifty feature to be able to override the default widgets on the model forms used by the admin interface and there is no reason not to allow the same level of tweaking with readonly fields. (http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides and http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-field-types-or-widgets)


comment:8 in reply to: ↑ 6 Changed 5 years ago by nickname123

Replying to cogat:

I'll have a crack at this.


Cool =).

comment:9 Changed 5 years ago by nickname123

A "to readonly html string" method on the field is a better idea. I misread your suggestion somewhat earlier. Like I said above, I hadn't put too much thought into the idea because I wasn't sure how other people would react to the feature request. Glad you gave some input =).

comment:10 Changed 4 years ago by anonymous

  • Severity set to Normal
  • Type set to New feature

comment:11 Changed 4 years ago by julien

  • UI/UX set

comment:12 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:13 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:14 Changed 3 years ago by aaugustin

  • UI/UX set

Revert accidental batch modification.

comment:15 Changed 2 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

I don't really like the idea of using a widget to render readonly fields, it just seems like overkill.

Note: See TracTickets for help on using tickets.
Back to Top