from django import forms from django.contrib import admin from django.contrib.admin.sites import site from django.contrib.admin.widgets import ManyToManyRawIdWidget, ForeignKeyRawIdWidget from django.core.urlresolvers import reverse from django.utils.encoding import smart_unicode from django.utils.html import escape class VerboseForeignKeyRawIdWidget(ForeignKeyRawIdWidget): def label_for_value(self, value): key = self.rel.get_related_field().name try: obj = self.rel.to._default_manager.using(self.db).get(**{key: value}) change_url = reverse( "admin:%s_%s_change" % (obj._meta.app_label, obj._meta.object_name.lower()), args=(obj.pk,) ) return ' %s' % (change_url, escape(obj)) except (ValueError, self.rel.to.DoesNotExist): return '???' class VerboseManyToManyRawIdWidget(ManyToManyRawIdWidget): def label_for_value(self, value): values = value.split(',') str_values = [] key = self.rel.get_related_field().name for v in values: try: obj = self.rel.to._default_manager.using(self.db).get(**{key: v}) x = smart_unicode(obj) change_url = reverse( "admin:%s_%s_change" % (obj._meta.app_label, obj._meta.object_name.lower()), args=(obj.pk,) ) str_values += ['%s' % (change_url, escape(x))] except self.rel.to.DoesNotExist: str_values += [u'???'] return u', '.join(str_values) class ImproveRawIdFieldsForm(admin.ModelAdmin): def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name in self.raw_id_fields: kwargs.pop("request", None) type = db_field.rel.__class__.__name__ if type == "ManyToOneRel": kwargs['widget'] = VerboseForeignKeyRawIdWidget(db_field.rel, site) elif type == "ManyToManyRel": kwargs['widget'] = VerboseManyToManyRawIdWidget(db_field.rel, site) return db_field.formfield(**kwargs) return super(ImproveRawIdFieldsForm, self).formfield_for_dbfield(db_field, **kwargs)