1. Listen to opening/closing Select2 events to add headers to the request:
{{{#!javascript
$(document).on("select2:opening", "#foo_set-group select.admin-
autocomplete", function () {
$.ajaxSetup({headers: {"X-Foo": "bar"}});
}
).on("select2:closing", "#foo_set-group select.admin-autocomplete",
function () {
delete $.ajaxSettings.headers["X-Foo"];
}
);
}}}
2. Destroy the widget and rebuild it using `$.fn.djangoAdminSelect2` to
hack my extra parameters next to the other expected GET parameters:
{{{#!python
let $select = $("#id_my_field");
$select.select2("destroy").djangoAdminSelect2({
ajax: {
data: function (params) {
return {
term: params.term
page: params.page
app_label: $select.data("app-label"),
model_name: $select.data("model-name"),
field_name: $select.data("field-name")
foo: "bar"
}
}
}
});
}}}
None of these solutions look clean to me, and I would definitely like to
have the ability to add extra parameters to `$.fn.djangoAdminSelect2`
properly as follows:
- `autocomplete.js`:
{{{#!javascript
'use strict';
{
const $ = django.jQuery;
const init = function($element, options, extraParams) {
const settings = $.extend({
ajax: {
data: function(params) {
let defaultParams = {
term: params.term,
page: params.page,
app_label: $element.data('app-label'),
model_name: $element.data('model-name'),
field_name: $element.data('field-name')
};
return $.extend(defaultParams, extraParams)
}
}
}, options);
$element.select2(settings);
};
$.fn.djangoAdminSelect2 = function(options, extraParams) {
const settings = $.extend({}, options);
$.each(this, function(i, element) {
const $element = $(element);
init($element, settings, extraParams);
});
return this;
};
$(function() {
// Initialize all autocomplete widgets except the one in the
template
// form used when a new formset is added.
$('.admin-
autocomplete').not('[name*=__prefix__]').djangoAdminSelect2();
});
$(document).on('formset:added', (function() {
return function(event, $newFormset) {
return $newFormset.find('.admin-
autocomplete').djangoAdminSelect2();
};
})(this));
}
}}}
- `consumer_script.js`:
{{{#!javascript
$select = $("#id_my_field");
$select.select2("destroy").djangoAdminSelect2({}, {foo: "bar"});
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32628>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Jan Staal):
There is another solution direction mentioned here:
https://stackoverflow.com/questions/55344987/how-to-filter-modeladmin-
autocomplete-fields-results-with-the-context-of-limit-c/55476825#55476825
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:1>
* cc: Johannes Maron (added)
* status: new => closed
* resolution: => duplicate
Comment:
Thanks for this proposition, however I don't think that JavaScript is the
right place to inject extra parameters. I would rather customize
`ModelAdmin.autocomplete_view()` and `AutocompleteJsonView`.
Closing as a duplicate of #29700 as documenting `AutocompleteJsonView` and
`ModelAdmin.autocomplete_view()` should fix this issue.
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:2>
Comment (by Seb G):
Thanks for both answers. However, I respectfully disagree with both of
them since both solutions are implemented back-end side and hence lack
flexibility for some scenario (including the ones I was opening this
ticket for).
Simplest example: I want to dynamically add the value of another field of
the form as an extra GET parameter to the autocomplete, to implement some
sort of fields-coupling.
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:3>
* type: Cleanup/optimization => New feature
* resolution: duplicate => wontfix
Comment:
> Thanks for both answers. However, I respectfully disagree with both of
them since both solutions are implemented back-end side and hence lack
flexibility for some scenario (including the ones I was opening this
ticket for).
>
> Simplest example: I want to dynamically add the value of another field
of the form as an extra GET parameter to the autocomplete, to implement
some sort of fields-coupling.
Agreed, there is a use case that is not covered by the current
implementation, however the Django Admin is not a
[https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#module-
django.contrib.admin universal tool for building an app]. You can always
override `autocomplete.js` in your project.
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:4>
Comment (by Johannes Maron):
Hi there,
The author of both the autocomplete integration as well as the django-
select2 package here.
So, I understand you point and frustration. However, the second solution
you are proposing actually looks a lot cleaner to me, than to arbitrarily
add a second options object.
Just of consistency I would keep the options we pass to
`djangoAdminSelect2` the same as the once you'd pass to `select2`. It
would make it very confusing for many folk if we break with the `select2`
API.
All that aside, this is not a public API. Therefore, your best bet is to
overwrite the whole file, if you need some special implementation or use
`django-select2` or your special needs.
Please, if you want to change the options object structure, I must kindly
ask you to try your luck with the Select2 project first. We simply don't
have the resources to maintain a custom implementation.
Best,
Joe
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:5>
Comment (by Seb G):
Thanks for clarifying the situation Johannes. I'll stick with my own
override then :-)
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:6>
Comment (by Seb G):
Dear Johannes,
I found the following code to both add the requested feature (being able
to add extra GET params to the AJAX request) **and** preserve Select2 API.
I also took the liberty of passing the `true` parameter to the `$.extend`
call that merges default Django settings with user-defined settings in the
`init` function (line 11), since omitting it caused a bug where other
parameters (passed through `options`) nested under the `ajax` key were
overwritten to `undefined` (see relevant documentation here:
https://api.jquery.com/jQuery.extend/#jQuery-extend-deep-target-
object1-objectN).
- `autocomplete.js`:
{{{#!javascript
'use strict';
{
const $ = django.jQuery;
const init = function($element, options) {
let userData = function (params) {};
if (options.ajax && options.ajax.data) {
userData = options.ajax.data;
delete options.ajax.data;
}
const settings = $.extend(true, {
ajax: {
data: function(params) {
const defaultData = {
term: params.term,
page: params.page,
app_label: $element.data('app-label'),
model_name: $element.data('model-name'),
field_name: $element.data('field-name')
};
return $.extend(defaultData, userData(params))
}
}
}, options);
$element.select2(settings);
};
$.fn.djangoAdminSelect2 = function(options) {
const settings = $.extend({}, options);
$.each(this, function(i, element) {
const $element = $(element);
init($element, settings);
});
return this;
};
$(function() {
// Initialize all autocomplete widgets except the one in the
template
// form used when a new formset is added.
$('.admin-
autocomplete').not('[name*=__prefix__]').djangoAdminSelect2();
});
$(document).on('formset:added', (function() {
return function(event, $newFormset) {
return $newFormset.find('.admin-
autocomplete').djangoAdminSelect2();
};
})(this));
}
}}}
- `consumer_script.js`:
{{{#!javascript
$select = $("#id_my_field");
$select.select2("destroy").djangoAdminSelect2({
ajax: {
data: function (params) {
return {foo: "bar"}
}
// Adding other AJAX settings is now also possible, such as
processResults for example
processResults: function (data) {
console.log("Now possible")
return data
}
}
});
}}}
Do you think this approach would be compatible with your flow?
Regards
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:7>
* status: closed => new
* resolution: wontfix =>
Comment:
For the record, I submitted a PR which was rejected since the flow seems
to be that an agreement should be reached here on Trac before moving on to
a PR. So could you please take a look either at the code here or at the
PR?
Link to the PR: https://github.com/django/django/pull/14305
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:8>
* status: new => closed
* resolution: => wontfix
Comment:
[https://docs.djangoproject.com/en/stable/internals/contributing/triaging-
tickets/#closing-tickets Please follow triaging guidelines with regards to
wontfix tickets.]
--
Ticket URL: <https://code.djangoproject.com/ticket/32628#comment:9>