Как сделать для моделей с ForeignKey (autocomplete_fields) многошаговый выбор в стандартном администраторе Django?

Вопрос по Django 2.0 с Select2 на коробке. Как сделать для моделей с ForeignKey (autocomplete_fields) многошаговый выбор в стандартном Django Admin?

Мое tours приложение:

tours/models.py:

class Tours(models.Model):
    country = models.ForeignKey(Countries, on_delete=None, default=None)
    resort = models.ForeignKey(Resorts, on_delete=None, null=True, default=None)

tours/admin.py:

@admin.register(Tours)
class ToursAdmin(admin.ModelAdmin):
    list_display = ('country', 'resort',)
    autocomplete_fields = ('country', 'resort',)

А это мое countries приложение:

countries/models.py:

class Countries(models.Model):
    name = models.CharField(max_length=255)

class Resorts(models.Model):
    name = models.CharField(max_length=255)
    country = models.ForeignKey(Countries, on_delete=models.CASCADE, default=None)

страны/admin.py:

class ResortsInlineAdmin(admin.StackedInline):
    model = Resorts

@admin.register(Countries) 
class CountriesAdmin(admin.ModelAdmin):
    list_display = ('name',)
    search_fields = ('name',)
    inlines = [ResortsInlineAdmin,]

@admin.register(Resorts)
class ResortsAdmin(admin.ModelAdmin):
    list_display = ('name', 'country',)
    search_fields = ('name',)

Было бы неплохо после выбора значения в поле Country — оставить в поле Resort только те значения, которые относятся к этому Country (опция inlines в countries/admin.py).

Аналогичная демонстрация с PHP + jQuery.


person koddr    schedule 11.01.2018    source источник
comment
Я ищу то же самое. Интересно, придется ли мне использовать django-select2 в качестве зависимости для этого?   -  person JLugao    schedule 15.01.2018
comment
@JLugao, в данный момент я решаю свой вопрос, добавляя в tours/admin.py дополнительный_контекст с идентификаторами Country и Resort и жестко запрограммированным шаблоном администратора (добавьте некоторый код jQuery для поля изменения и перестройте в них массив идентификаторов).   -  person koddr    schedule 16.01.2018


Ответы (1)


Ответ слишком простой, но я много часов в Google.

Во-первых, добавлен дополнительный контекст для tours/admin.py (ModelAdmin.change_view()):

# tours/admin.py

@admin.register(Tours)
class ToursAdmin(admin.ModelAdmin):
    list_display = ('country', 'resort',)
    autocomplete_fields = ('country', 'resort',)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['resort_to_country'] = Resorts.objects.all().values_list('pk', 'country_id')
        return super().change_view(
            request, object_id, form_url, extra_context=extra_context,
        )

Затем улучшите templates/admin/tours/add_form.html с помощью JavaScript, например:

// on bottom, into <script></script> tag:

var resort_to_country = [
    {% for i in resort_to_country %}
        ['{{ i.country }}', {{ i.pk }}, '{{ i.name }}'],
    {% endfor %}
];

var resorts_select_field = django.jQuery('#id_resort');
var countries_select_field = django.jQuery('#id_country');

countries_select_field.on('change', function () {
    resorts_select_field.empty();
    resort_to_country.forEach(function (item) {
        if (item[0] === countries_select_field.find(':selected').text()) {
            resorts_select_field.append(django.jQuery('<option></option>').attr('value', item[1]).text(item[2]));
        }
    });
});

Это все.

person koddr    schedule 27.01.2018
comment
у вас есть пример git полного кода для этого, пожалуйста? У меня невероятно похожая ситуация, но я не знаю, как обновить html/where - person Rach Odwyer; 14.02.2019