Login

Replace model select widget in admin with a readonly link to the related object

Author:
ekellner
Posted:
August 28, 2008
Language:
Python
Version:
.96
Tags:
admin field widget readonly modelchoicefield
Score:
6 (after 6 ratings)

This replaces the html select box for a foreign key field with a link to that object's own admin page. The foreign key field (obviously) is readonly.

This is shamelessly based upon the Readonly admin fields snippet. However, that snippet didn't work for me with ForeignKey fields.

from foo.bar import ModelLinkAdminFields

class MyModelAdmin(ModelLinkAdminFields, admin.ModelAdmin):
    modellink = ('field1', 'field2',)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from django import forms
from django.utils.safestring import mark_safe
from django.utils.html import escape

class ModelLinkWidget(forms.HiddenInput):

    def __init__(self, admin_site, original_object):
        self.admin_site = admin_site
        self.original_object = original_object
        super(ModelLinkWidget,self).__init__()

   
    def render(self, name, value, attrs=None):
        if self.original_object is not None:
            link = '%s%s/%s/%d' % (self.admin_site.root_path,
                                   self.original_object._meta.app_label, 
                                   self.original_object._meta.module_name,
                                   self.original_object.id)
            return super(ModelLinkWidget, self).render(
                name, value, attrs) + mark_safe('<a href="%s">%s</a>' % (link, escape(unicode(self.original_object))))
        else:
            return "None"
                                                                
class ModelLinkAdminFields(object):
    def get_form(self, request, obj=None):
        form = super(ModelLinkAdminFields, self).get_form(request, obj)

        if hasattr(self, 'modellink'):
            for field_name in self.modellink:
                if field_name in form.base_fields:
                    form.base_fields[field_name].widget = ModelLinkWidget(self.admin_site, getattr(obj, field_name, ''))
                    form.base_fields[field_name].required = False
        return form

More like this

  1. autocompleter with database query by bbolli 8 years ago
  2. Javascript Chain Select Widget by ogo 7 years, 1 month ago
  3. Select or Create widget by Naster 1 year, 5 months ago
  4. Querying on existence of a relationship by ubernostrum 7 years, 12 months ago
  5. Readonly Select Widget Replacement by colinkingswood 7 months, 3 weeks ago

Comments

romke (on December 12, 2008):

I'd put "self.original_object.pk" instead of "self.original_object.id" as sometimes you have primary key named differently than "id"

#

paulmcm (on February 11, 2009):

This worked for me, except when I wanted to add a new item in the admin containing the field in question (I was using it to show ID fields).

The fix (for me) was to modify line 13 to read:

        if (self.original_object is not None) and (hasattr(self.original_object, '_meta')):

now it no longer throws the error for me.

#

graeme (on June 28, 2009):

I was getting errors when there was a null value in a foreign key (pointing to User).

Changing some lines in ModelLinkAdminFields fixed it:

    if hasattr(self, 'modellink'):
        for field_name in self.modellink:
            if field_name in form.base_fields:
                try:
                    y = getattr(obj, field_name, None)
                except:
                    y = None
                form.base_fields[field_name].widget = ModelLinkWidget(self.admin_site, y)

I am not sure this is the best only way, and only fields that had been filled in by django-evolution caused problems, so this probably will not affect everyone.

#

Please login first before commenting.