Opened 6 years ago

Closed 3 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: Greg Turner
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 Changed 6 years ago by Greg Turner

Keywords: sprintdec2010 added
Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Resolution: wontfix
Status: newclosed
Triage Stage: UnreviewedDesign 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 ; Changed 6 years ago by nickname123

Resolution: wontfix
Status: closedreopened

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 ; Changed 6 years ago by Greg Turner

milestone: 1.3

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 6 years ago by Greg Turner

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

comment:5 Changed 6 years ago by Greg Turner

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

comment:6 Changed 6 years ago by Greg Turner

Owner: changed from nobody to Greg Turner
Status: reopenednew

I'll have a crack at this.

comment:7 in reply to:  3 Changed 6 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 6 years ago by nickname123

Replying to cogat:

I'll have a crack at this.


Cool =).

comment:9 Changed 6 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 5 years ago by anonymous

Severity: Normal
Type: New feature

comment:11 Changed 5 years ago by Julien Phalip

UI/UX: set

comment:12 Changed 5 years ago by Aymeric Augustin

UI/UX: unset

Change UI/UX from NULL to False.

comment:13 Changed 5 years ago by Aymeric Augustin

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:14 Changed 5 years ago by Aymeric Augustin

UI/UX: set

Revert accidental batch modification.

comment:15 Changed 3 years ago by Jacob

Resolution: wontfix
Status: newclosed

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