Фильтр Django на основе объединенной модели - PullRequest
0 голосов
/ 17 января 2019

Допустим, у меня есть следующий дизайн

таблица базы данных

A track имеет song, а song имеет singer.Мне бы хотелось, чтобы дорожка позволяла выполнять фильтрацию по имени певца.

Итак, мне нужна модель track, извлекающая имя singer.Я застрял с фильтрами.

Я получаю следующее сообщение об ошибке:

File ".../lib/python3.6/site-packages/django_filters/filterset.py", line 352, in get_filters
    "%s" % ', '.join(undefined)
TypeError: 'Meta.fields' contains fields that are not defined on this FilterSet: singer

Я слышал от этот , чтобы использовать __, но я понятия не имеюкак это применить.

Вот код

class TrackSerializer(MyModelSerializer):
    singer = serializers.SerializerMethodField()

    def get_singer(self, track): # Is there any shortcut?
        song = Song.objects.get(id=track.song_id)
        if song is not None:
            return Channel.objects.get(id=song.singer_id).name
        else:
            return ''

    class Meta:
        model = Track
        fields = (
            'id',
            'name',
            'song',
            'singer',
        )

class TrackFilterSet(MyFilterSet):
    singer = CharFilter(method='singer_filter')
    song = RefineModelChoiceFilter(
        queryset=Song.objects.all(),
        refine_choices=lambda qs, keywords, request: qs.filter(name__icontains=keywords)
    )

    def singer_filter(self, queryset, name, value):
        # print('queryset:', TrackSerializer(queryset, many=True))
        return queryset.filter(**{
            name: value,  # ???????????
        })

    class Meta:
        model = Track
        fields = (
            'singer',
            'song',
        )


class TrackViewSet(MyViewSet):
    queryset = Track.objects.all()
    serializer_class = TrackSerializer
    filterset_fields = ('singer', 'song')

    def filter_refine_choices_singer(self, qs, keywords, request):
        return qs.filter(name__icontains=keywords)

    def filter_refine_choices_song(self, qs, keywords, request):
        return qs.filter(name__icontains=keywords)

Ответы [ 2 ]

0 голосов
/ 26 июня 2019

попробуйте поместить filterset_fields в массив, между [], а не ().

filterset_fields = ['singer', 'song']
0 голосов
/ 17 января 2019

Я думаю, что метод singer_filter вы должны так что-то вроде:

def singer_filter(self, queryset, name, value):
    return queryset.filter(song_id__singer_id__name_icontains=value)

Я не проверял это, но я думаю, что-то подобное должно работать, если только третье отношение __ не разрешено. Посмотрите здесь: https://django -filter.readthedocs.io / о / мастер / исй / filters.html? Изюминка = метод

...