-
Notifications
You must be signed in to change notification settings - Fork 6
/
relatives.py
90 lines (79 loc) · 2.87 KB
/
relatives.py
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
from django.template import Library
from django.urls import reverse, NoReverseMatch
from django.utils.encoding import smart_text
from django.utils.safestring import mark_safe
from django.contrib.admin.utils import lookup_field
from django.core.exceptions import ObjectDoesNotExist
from ..utils import get_admin_url, GenericObjects
register = Library()
@register.filter
def contents_or_fk_link(field):
"""
Return field contents or link to related object if foreign key field
Example Usage::
{% load relatives %}
{{ field|contents_or_fk_link }}
"""
contents = field.contents()
field_name = field.field['field']
obj = field.form.instance
if not isinstance(field_name, str):
return contents
try:
related_obj = getattr(obj, field_name)
except (AttributeError, ObjectDoesNotExist):
return contents
else:
model_field, _, _ = lookup_field(field_name, obj, field.model_admin)
if ((model_field is None or model_field.remote_field)
and hasattr(related_obj, '_meta')):
try:
return mark_safe('<a href="%s">%s</a>' %
(get_admin_url(related_obj), contents))
except NoReverseMatch:
pass
return contents
@register.simple_tag
def related_objects(obj):
"""
Return list of objects related to the given model instance
Example Usage::
{% load relatives %}
{% related_objects obj as related_objects %}
{% for related_obj in related_objects %}
<a href="{{ related_obj.url }}">{{ related_obj.plural_name }}</a>
{% endfor %}
"""
object_list = []
all_related_objects = [
field
for field in obj._meta.get_fields()
if (field.one_to_many or field.one_to_one)
and field.auto_created and not field.concrete
]
all_related_m2m_objects = [
field
for field in obj._meta.get_fields(include_hidden=True)
if field.many_to_many and field.auto_created
]
related_objects = (all_related_objects
+ all_related_m2m_objects
+ GenericObjects(obj).get_generic_objects())
for related in related_objects:
try:
to_model = getattr(related, 'related_model', related.model)
url = reverse('admin:{0}_{1}_changelist'.format(
to_model._meta.app_label,
to_model._meta.model_name
))
except NoReverseMatch:
continue
if getattr(related, 'related_name', None):
plural_name = related.related_name.replace("_", " ")
else:
plural_name = to_model._meta.verbose_name_plural
object_list.append({
'plural_name': plural_name,
'url': smart_text('%s?%s=%s' % (url, related.field.name, obj.pk)),
})
return object_list