django-фильтры, использующие ModelChoiceFilter для получения значения ForeignKey - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь использовать ModelChoiceFilter для фильтрации базы данных писем на основе автора.Автор - ForeignKey, и я не могу заставить его отобразить значение «name» для ForeignKey.

Вот что у меня есть:

models.py (ограничено релевантнымбиты)

class Person(models.Model):
    name = models.CharField(max_length=250, verbose_name='Full Name')
    ...

    def __str__(self):
        return self.name

class Letter(models.Model):
    author = models.ForeignKey(Person, related_name='author', on_delete=models.PROTECT, verbose_name='Letter Author')
    recipient = models.ForeignKey(Person, related_name='recipient', on_delete=models.PROTECT, verbose_name='Recipient')
    ...
    title = models.CharField(max_length=250, verbose_name='Title of Letter')

    def __str__(self):
        return self.title

letter_filters.py

class LetterFilter(django_filters.FilterSet):
    ...
    author = django_filters.ModelChoiceFilter(queryset=Letter.objects.order_by('author__name'))

    class Meta:
        model = Letter
        fields = ['author', 'recipient']

Я вижу, что этот вид работает.Это действительно ограничивает и упорядочивает это должным образом, но вместо имени автора, представленного в поле выбора, он представляет «заголовок» из буквы (но я могу сказать из заголовка в правильном порядке).

То, что я думал, должно работать так:

fields = ['author__name', 'recipient']

Но это также продолжает перечислять "заголовок" из письма вместо "имени" из персоны.

Я знаюу него есть то, что мне нужно, потому что, если я делаю:

 author = django_filters.ModelChoiceFilter(queryset=Letter.objects.order_by('author__name').values('author__name'))

, я получаю именно то, что хочу!Но он представлен как {'author__name': 'Jane Doe'} с полями author или author_name.Кажется, я просто не могу получить правильный синтаксис.

Наконец, я знаю, что могу сделать:

author = django_filters.ModelChoiceFilter(queryset=Person.objects.order_by('name'))

, который возвращает всех людей, правильно упорядоченных.Однако в базе данных гораздо больше людей, чем просто авторов.Это тот же результат, что и просто разрешение полей по умолчанию ['author' ... без установки author = в классе (хотя и неупорядочено).

1 Ответ

0 голосов
/ 25 июня 2018

Итак, указанный вами набор запросов имеет дело с Letter с, поэтому в результате Letter с добавляются в ModelChoiceFiler, что не совсем идеально.

Однако вы можете сгенерировать список Person с написанием хотя бы одной буквы, например:

django_filters.ModelChoiceFilter(
    queryset=Person.objects<b>.filter(letter_set__isnull=False).order_by('name').distinct()</b>
)

Таким образом, здесь мы фильтруем тот факт, что letter_set не является пустым, и, поскольку это приведет к JOIN, где Person может произойти несколько раз, мы добавляем .distinct() к нему.

Я считаю это моделирование очень странным (в ваших трех примерах). В основном это означает, что вы можете назначить только Person s, которые уже написали Letter. Что если человек, который никогда не писал Letter, хочет написать Letter?

Обычно, если такие роли разные, вы можете, например, добавить BooleanField:

class Person(models.Model):
    name = models.CharField(max_length=250, verbose_name='Full Name')
    <b>is_author = models.BooleanField(verbose_name='Is the person an author')</b>
    # ...

Затем мы можем отфильтровать по Person с, которые Author с:

django_filters.ModelChoiceFilter(
    queryset=Person.objects.filter(<b>is_author=True</b>).order_by('name')
)
...