|
1 from django import forms |
|
2 from django.conf import settings |
|
3 from django.utils.safestring import mark_safe |
|
4 from django.utils.text import truncate_words |
|
5 from django.template.loader import render_to_string |
|
6 from django.contrib.admin.widgets import ForeignKeyRawIdWidget |
|
7 |
|
8 class ForeignKeySearchInput(ForeignKeyRawIdWidget): |
|
9 """ |
|
10 A Widget for displaying ForeignKeys in an autocomplete search input |
|
11 instead in a <select> box. |
|
12 """ |
|
13 # Set in subclass to render the widget with a different template |
|
14 widget_template = None |
|
15 # Set this to the patch of the search view |
|
16 search_path = '../foreignkey_autocomplete/' |
|
17 |
|
18 class Media: |
|
19 css = { |
|
20 'all': ('django_extensions/css/jquery.autocomplete.css',) |
|
21 } |
|
22 js = ( |
|
23 'django_extensions/js/jquery.js', |
|
24 'django_extensions/js/jquery.bgiframe.min.js', |
|
25 'django_extensions/js/jquery.ajaxQueue.js', |
|
26 'django_extensions/js/jquery.autocomplete.js', |
|
27 ) |
|
28 |
|
29 def label_for_value(self, value): |
|
30 key = self.rel.get_related_field().name |
|
31 obj = self.rel.to._default_manager.get(**{key: value}) |
|
32 return truncate_words(obj, 14) |
|
33 |
|
34 def __init__(self, rel, search_fields, attrs=None): |
|
35 self.search_fields = search_fields |
|
36 super(ForeignKeySearchInput, self).__init__(rel, attrs) |
|
37 |
|
38 def render(self, name, value, attrs=None): |
|
39 if attrs is None: |
|
40 attrs = {} |
|
41 output = [super(ForeignKeySearchInput, self).render(name, value, attrs)] |
|
42 opts = self.rel.to._meta |
|
43 app_label = opts.app_label |
|
44 model_name = opts.object_name.lower() |
|
45 related_url = '../../../%s/%s/' % (app_label, model_name) |
|
46 params = self.url_parameters() |
|
47 if params: |
|
48 url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) |
|
49 else: |
|
50 url = '' |
|
51 if not attrs.has_key('class'): |
|
52 attrs['class'] = 'vForeignKeyRawIdAdminField' |
|
53 # Call the TextInput render method directly to have more control |
|
54 output = [forms.TextInput.render(self, name, value, attrs)] |
|
55 if value: |
|
56 label = self.label_for_value(value) |
|
57 else: |
|
58 label = u'' |
|
59 context = { |
|
60 'url': url, |
|
61 'related_url': related_url, |
|
62 'admin_media_prefix': settings.ADMIN_MEDIA_PREFIX, |
|
63 'search_path': self.search_path, |
|
64 'search_fields': ','.join(self.search_fields), |
|
65 'model_name': model_name, |
|
66 'app_label': app_label, |
|
67 'label': label, |
|
68 'name': name, |
|
69 } |
|
70 output.append(render_to_string(self.widget_template or ( |
|
71 'django_extensions/widgets/%s/%s/foreignkey_searchinput.html' % (app_label, model_name), |
|
72 'django_extensions/widgets/%s/foreignkey_searchinput.html' % app_label, |
|
73 'django_extensions/widgets/foreignkey_searchinput.html', |
|
74 ), context)) |
|
75 output.reverse() |
|
76 return mark_safe(u''.join(output)) |