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))
|
---|