Объединение двух таблиц и поиск/фильтр в сериализованных данных с помощью django-rest-framework

Я объединяю две таблицы и хочу выполнить поиск по ключевым словам. Мне нужно создать один SQL и добавить WHERE с аргументом(ами). Я использую django-rest-framework.

models.py

from django.db import models


class Paper(models.Model):
    title = models.TextField()
    paper_lan = models.CharField(max_length=2)
    nb_authors = models.SmallIntegerField()

    class Meta:
        managed = False

    def __str__(self):
        return str(self.title)

class Abstract(models.Model):
    paper = models.OneToOneField(Paper,
                                 related_name='abstracts',
                                 on_delete=models.CASCADE,
                                 primary_key=True)
    abstract = models.TextField()

    class Meta:
        managed = False

    def __str__(self):
        return str(self.abstract)

serializers.py

from rest_framework import serializers
from .models import Paper, Abstract


class PaperAbstractSerializer(serializers.ModelSerializer):
    class Meta:
        model = Paper
        #fields = '__all__'
        fields = ['title', 'paper_lan', 'nb_authors', 'abstracts']
        depth = 1

class PaperSerializer(serializers.ModelSerializer):
    class Meta:
        model = Paper
        fields = ('title', 'paper_lan', 'nb_authors')

class AbstractSerializer(serializers.ModelSerializer):
    class Meta:
        model = Abstract
        fields = ['abstract']

filters.py

from django.db.models import Q
from django_filters.rest_framework import CharFilter, FilterSet
from .models import Paper, Abstract


class PaperAbstractFilterSet(FilterSet):
    query = CharFilter(method='qfilter')

    class Meta:
        model = Paper
        fields = ['query']

    def qfilter(self, queryset, name, value):
        squery = Q(abstracts__icontains=value)

        return queryset.filter(squery)

class PaperFilterSet(FilterSet):
    query = CharFilter(method='qfilter')

    class Meta:
        model = Paper
        fields = ['query']

    def qfilter(self, queryset, name, value):
        squery = Q(title__icontains=value)

        return queryset.filter(squery)

class AbstractFilterSet(FilterSet):
    query = CharFilter(method='qfilter')

    class Meta:
        model = Abstract
        fields = ['query']

    def qfilter(self, queryset, name, value):
        squery = Q(abstract__icontains=value)

        return queryset.filter(squery)

views.py

from rest_framework.generics import ListAPIView
from .models import Paper, Abstract
from .serializers import PaperAbstractSerializer, PaperSerializer, AbstractSerializer
from .filters import PaperAbstractFilterSet, PaperFilterSet, AbstractFilterSet


class PaperAbstractView(ListAPIView):
    queryset = Paper.objects.all()
    serializer_class = PaperAbstractSerializer
    filterset_class = PaperAbstractFilterSet

class PaperView(ListAPIView):
    queryset = Paper.objects.all()
    serializer_class = PaperSerializer
    filterset_class = PaperFilterSet

class AbstractView(ListAPIView):
    queryset = Abstract.objects.all()
    serializer_class = AbstractSerializer
    filterset_class = AbstractFilterSet

urls.py

from django.urls import path
from .views import PaperAbstractView, PaperView, AbstractView


urlpatterns = [
    path('paperabs/', PaperAbstractView.as_view()),
    path('paper/', PaperView.as_view()),
    path('abstract/', AbstractView.as_view()),
]

Когда я выполняю следующие действия, поиск производится в одной таблице, все в порядке. Есть только один SQL, который производится.

curl "http://localhost:8003/api/v1/appln/abstract/?query=<keyword_searching>"
curl "http://localhost:8003/api/v1/appln/paper/?query=<keyword_searching>"

Но когда я выполняю следующий запрос, я не могу выполнить поиск по ключевым словам. Если я закомментирую строку filterset_class = PaperAbstractFilterSet в PaperAbstractView, появится один SQL, а затем, соответственно, n других SQL, созданных для второй таблицы.

curl "http://localhost:8003/api/v1/appln/paperabs/?query=<keyword_searching>"

Как создать один SQL с дополнительным WHERE для проведения любого поиска по названию и/или реферату?

Чтобы ответить на свой вопрос; для объединения двух таблиц в одном SQL я использую select_related и корректирую serializers.py, добавляя сериализатор LEFT JOINed table, AbstractSerializer в PaperAbstractSerializer.

# serializers.py

class PaperAbstractSerializer(serializers.ModelSerializer):
    abstracts = AbstractSerializer(read_only=True)
    class Meta:
        model = Paper
        fields = ['title', 'paper_lan', 'nb_authors', 'abstracts']


# views.py

class PaperAbstractView(ListAPIView):
    queryset = Paper.objects.select_related('abstracts').all()
    serializer_class = PaperAbstractSerializer
    filterset_class = PaperAbstractFilterSet
Вернуться на верх