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