Отфильтруйте окно ManyToMany в Django Admin - PullRequest
34 голосов
/ 04 августа 2009

У меня есть объект, имеющий отношение многие ко многим с другим объектом.
В Django Admin это приводит к очень длинному списку в окне множественного выбора.

Я бы хотел отфильтровать отношение ManyToMany, чтобы я выбирал только те категории, которые доступны в городе, выбранном клиентом.

Возможно ли это? Должен ли я создать виджет для него? И если да, то как мне скопировать в него поведение из стандартного поля ManyToMany, поскольку мне также нужна функция filter_hor Horizontal.

Это мои упрощенные модели:

class City(models.Model):
    name = models.CharField(max_length=200)


class Category(models.Model):
    name = models.CharField(max_length=200)
    available_in = models.ManyToManyField(City)


class Customer(models.Model):
    name = models.CharField(max_length=200)
    city = models.ForeignKey(City)
    categories = models.ManyToManyField(Category)

Ответы [ 7 ]

36 голосов
/ 09 августа 2009

Хорошо, это мое решение с использованием вышеуказанных классов. Я добавил еще несколько фильтров для правильной фильтрации, но я хотел, чтобы код читался здесь.

Это именно то, что я искал, и я нашел свое решение здесь: http://www.slideshare.net/lincolnloop/customizing-the-django-admin#stats-bottom (слайд 50)

Добавьте следующее в мой admin.py:

class CustomerForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs):
        super(CustomerForm, self).__init__(*args, **kwargs)
        wtf = Category.objects.filter(pk=self.instance.cat_id);
        w = self.fields['categories'].widget
        choices = []
        for choice in wtf:
            choices.append((choice.id, choice.name))
        w.choices = choices


class CustomerAdmin(admin.ModelAdmin):
    list_per_page = 100
    ordering = ['submit_date',] # didnt have this one in the example, sorry
    search_fields = ['name', 'city',]
    filter_horizontal = ('categories',)
    form = CustomerForm

Это фильтрует список "категорий", не удаляя никакой функциональности! (то есть: у меня все еще может быть мой любимый фильтр_горизонтальный:))

ModelForms очень мощные, я немного удивлен, что это больше не рассматривается в документации / книге.

15 голосов
/ 04 августа 2009

Насколько я вас понимаю, вы в основном хотите отфильтровать показанные варианты выбора по некоторым критериям (категория по городу).

Вы можете сделать это точно, используя limit_choices_to атрибут models.ManyToManyField. Так что изменив определение модели как ...

class Customer(models.Model):
    name = models.CharField(max_length=200)
    city = models.ForeignKey(City)
    categories = models.ManyToManyField(Category, limit_choices_to = {'available_in': cityId})

Это должно работать, так как limit_choices_to доступно для этой цели.

Но обратите внимание: limit_choices_to не действует при использовании ManyToManyField с пользовательской промежуточной таблицей. Надеюсь, это поможет.

5 голосов
/ 30 апреля 2016

Другой способ - с formfield_for_manytomany в Django Admin.

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "cars":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

Учитывая, что "автомобили" - это поле ManyToMany.

Проверьте эту ссылку для получения дополнительной информации.

2 голосов
/ 10 декабря 2010

Я думаю, это то, что вы ищете:

http://blog.philippmetzler.com/?p=52

мы используем django-smart-select:

http://github.com/digi604/django-smart-selects

Philipp

1 голос
/ 04 августа 2009

Поскольку вы выбираете город и категории клиента в одной и той же форме, вам понадобится некоторый javascript для динамического сокращения селектора категорий только до тех категорий, которые доступны в выбранном городе.

0 голосов
/ 15 декабря 2009

Как говорит Райан, должен быть какой-то javascript для динамического изменения параметров в зависимости от того, что выбирает пользователь. Размещенное решение работает, если город сохранен и административная форма перезагружена, то есть, когда фильтр работает, но подумайте о ситуации, когда пользователь хочет отредактировать объект, а затем изменить раскрывающийся список городов, но параметры в категории не обновятся.

0 голосов
/ 04 августа 2009
Category.objects.filter(available_in=cityobject)

Это должно сделать это. В представлении должен быть выбран город, выбранный пользователем, либо в запросе, либо в качестве параметра этой функции представления.

...