Ticket #10743: patch.diff

File patch.diff, 4.9 KB (added by Rilt, 14 years ago)
Line 
1Index: django/contrib/admin/validation.py
2===================================================================
3--- django/contrib/admin/validation.py (revision 12223)
4+++ django/contrib/admin/validation.py (working copy)
5@@ -1,5 +1,6 @@
6 from django.core.exceptions import ImproperlyConfigured
7 from django.db import models
8+from django.db.models.sql.constants import LOOKUP_SEP
9 from django.forms.models import (BaseModelForm, BaseModelFormSet, fields_for_model,
10 _get_foreign_key)
11 from django.contrib.admin.options import flatten_fieldsets, BaseModelAdmin
12@@ -32,8 +33,11 @@
13 try:
14 opts.get_field(field)
15 except models.FieldDoesNotExist:
16- raise ImproperlyConfigured("%s.list_display[%d], %r is not a callable or an attribute of %r or found in the model %r."
17- % (cls.__name__, idx, field, cls.__name__, model._meta.object_name))
18+ try:
19+ get_closest_relation(model, field)
20+ except AttributeError, models.FieldDoesNotExist:
21+ raise ImproperlyConfigured("%s.list_display[%d], %r is not a callable or an attribute of %r or found in the model %r."
22+ % (cls.__name__, idx, field, cls.__name__, model._meta.object_name))
23 else:
24 # getattr(model, field) could be an X_RelatedObjectsDescriptor
25 f = fetch_attr(cls, model, opts, "list_display[%d]" % idx, field)
26@@ -349,3 +353,28 @@
27 except AttributeError:
28 raise ImproperlyConfigured("'%s.%s' refers to '%s' that is neither a field, method or property of model '%s'."
29 % (cls.__name__, label, field, model.__name__))
30+
31+def get_closest_relation(model,relation):
32+ # Recursively go down all forward relations, then all backward relations with this model to see if the relation exists.
33+ if not LOOKUP_SEP in relation:
34+ if hasattr(model,'base') and relation in model.base.field.rel.to._meta.get_all_field_names():
35+ """
36+ If this model has a base class and the field is really on it,
37+ return the actual base class.
38+ """
39+ model = model.base.field.rel.to
40+ return model._meta.get_field_by_name(relation) # at this point we should have our field, or it raises FieldDoesNotExist
41+
42+ this_module = relation.split(LOOKUP_SEP,1)
43+
44+ if this_module[0] in model._meta.get_all_field_names(): # forward relations
45+ rel = model._meta.get_field_by_name(this_module[0])[0].rel
46+ if isinstance(rel,models.fields.related.OneToOneRel) or isinstance(rel,models.fields.related.ManyToOneRel):
47+ return get_closest_relation(rel.to,this_module[1])
48+
49+ for rel in model._meta.get_all_related_objects(): # backward relations
50+ if this_module[0] in (rel.name, rel.field.related_query_name) and isinstance(rel,models.fields.related.OneToOneRel):
51+ return get_closest_relation(rel.model,this_module[1])
52+
53+ raise AttributeError("%s relation not found on %s." % (this_module[0],model._meta.verbose_name))
54Index: django/contrib/admin/util.py
55===================================================================
56--- django/contrib/admin/util.py (revision 12223)
57+++ django/contrib/admin/util.py (working copy)
58@@ -1,5 +1,6 @@
59 from django.core.exceptions import ObjectDoesNotExist
60 from django.db import models
61+from django.db.models.sql.constants import LOOKUP_SEP
62 from django.utils import formats
63 from django.utils.html import escape
64 from django.utils.safestring import mark_safe
65@@ -229,9 +230,13 @@
66 try:
67 f = opts.get_field(name)
68 except models.FieldDoesNotExist:
69- # For non-field values, the value is either a method, property or
70- # returned via a callable.
71- if callable(name):
72+ # For non-field values, the value is either a relation, method, property or
73+ # returned via a callable
74+ if type(name) == str and LOOKUP_SEP in name:
75+ value = obj
76+ for attr in name.split(LOOKUP_SEP):
77+ value = getattr(value,attr)
78+ elif callable(name):
79 attr = name
80 value = attr(obj)
81 elif (model_admin is not None and hasattr(model_admin, name) and
82@@ -259,6 +264,8 @@
83 label = force_unicode(model._meta.verbose_name)
84 elif name == "__str__":
85 label = smart_str(model._meta.verbose_name)
86+ elif type(name) == str and LOOKUP_SEP in name:
87+ label = name.split(LOOKUP_SEP)[-1].replace('_',' ')
88 else:
89 if callable(name):
90 attr = name
91@@ -286,7 +293,6 @@
92 else:
93 return label
94
95-
96 def display_for_field(value, field):
97 from django.contrib.admin.templatetags.admin_list import _boolean_icon
98 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
99
Back to Top