Как получить поля из Serializer в ListView для фильтрации - PullRequest
0 голосов
/ 11 апреля 2020

рассматриваемая модель:

class CustomerPrices(models.Model):
    url = models.OneToOneField('CustomerProductUrls', models.DO_NOTHING, db_column="url", primary_key=True)
    written = models.DateTimeField()
    reseller = models.CharField(max_length=250)
    price = models.FloatField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'customer_prices'
        unique_together = (('url', 'written', 'reseller'),)

рассматриваемый сериализатор (и один связанный с ним сериализатор):

class CustomerProductUrlsSerializer(serializers.ModelSerializer):
    ean = CustomerProductsSerializer()
    url = serializers.CharField(max_length=255, required=False)
    class Meta:
        model = CustomerProductUrls
        fields = '__all__'

class CustomerPricesSerializer(serializers.ModelSerializer):
    written = serializers.DateTimeField(format='%Y-%m-%d %H:%M:00', required=False)
    reseller = serializers.CharField(max_length=250, required=False)
    url = CustomerProductUrlsSerializer()
    name = serializers.SerializerMethodField('get_name')
    ean = serializers.SerializerMethodField('get_ean')
    url = serializers.SerializerMethodField('get_url')
    price = serializers.FloatField()

    class Meta:
        model = CustomerPrices
        fields = '__all__'

    def get_name(self, obj):
        return obj.url.ean.name

    def get_ean(self, obj):
        return obj.url.ean.ean

    def get_url(self, obj):
        return obj.url.url

и ListAPIView для класса CustomerPrices:

class CustomerPricesListView(generics.ListAPIView):
    serializer_class = CustomerPricesSerializer
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    fields = ('written', 'url', 'price')
    filter_fields = fields
    search_fields = fields
    def get_queryset(self):
        """
        This view should return a list of all the products where price >= 70
        """
        return CustomerPrices.objects.filter(price__gte=70)

Внутри моего CustomerPricesSerializer у меня есть поле с именем ean, а также name значения для этих двух поступают через связанный CustomerProductUrlsSerializer (и соответствующую модель). Код работает до сих пор, я получаю ответ, похожий на этот:

"results": [
    {
        "url": "https://www.example.com/p/12345678",
        "written": "2020-04-05 12:00:00",
        "reseller": "ABC123",
        "name": "Product 12345678",
        "ean": "1234567890123",
        "price": 98.3
    }, ... 
    ]

Я использую DjangoFilterBackend, и я хотел бы фильтровать на ean, а также name , который доступен в моем ответе. Но как только я добавляю ean к своему fields каркасу внутри Сериализатора, я получаю Meta.fields contains fields that are not defined on this FilterSet: ean. Я понимаю, что мой queryset возвращает поля из CustomerPrices Model внутри моего ListAPIView, но как мне получить ean, а также name, чтобы быть частью набора запросов и, следовательно, частью в наличии fields

1 Ответ

1 голос
/ 11 апреля 2020

Поле ean относится не к модели CustomerPrices, а где-то еще. DRF ожидает, что кортежи фильтров напрямую связаны с моделью (здесь CustomerPrices) и, следовательно, с ошибкой.

Чтобы решить эту проблему, необходимо указать фактическое отношение в поле ean.

class CustomerPricesListView(generics.ListAPIView):
    fields = ('written', 'url', 'price', <b>'url__ean__ean', 'url__ean__name'</b>)
    filter_fields = fields
    # rest of the code
...