首页 > 解决方案 > 将带有注释的 django 查询集发送到我的 rest api

问题描述

我有两个简单的模型,其中包含有关手机的随机数据。

class Phone(models.Model):
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=400)
    image = models.ImageField(upload_to='phone_img/', max_length=255, null=True, blank=True )
    slug_phone = models.SlugField(blank=True)

class Price(models.Model):
    price = models.DecimalField(max_digits=6, decimal_places=2)
    date = models.DateField(null=True, blank=True) 
    phone = models.ForeignKey(Phone, on_delete=models.CASCADE)
    market = models.ForeignKey(Market, on_delete=models.CASCADE)

我能够通过 REST_framework 的数据将简单数据发送到我的 API。

视图.py

class SnippetList(generics.ListCreateAPIView):
    queryset = Price.objects.all()
    serializer_class = PriceSerializer

序列化程序.py

class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        fields = ('id', 'phone', 'price', 'date', 'market', )


    phone = serializers.StringRelatedField()
    market = serializers.StringRelatedField()

现在我想在 QuerySet 中使用带有Min()函数的annotate()方法。我想显示每部手机的最低价格。所以我尝试了这样的事情:

视图.py

from django.db.models import Min

<....>

class SnippetList(generics.ListCreateAPIView):
    queryset = Price.objects.all()
    serializer_class = PriceSerializer
    def get_queryset(self):
        min_price = Phone.objects.annotate(Min('price__price'))

        return min_price

当然这没有用。我跟随服务器错误消息并以此结束:

序列化程序.py

from rest_framework import serializers
from market.models import Price, Phone


class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        fields = ('id', 'phone', 'price', 'date', 'market')

    class Meta:
        model = Phone
        fields = ('name', 'phone', 'market', )


    phone = serializers.StringRelatedField()
    market = serializers.StringRelatedField()

我的API现在向我显示了这个输出,它不是 min_price 值,但至少是一些东西:

{"count":7,"next":null,"previous":null,"results":[{"name":"SAMSUNG Galaxy S10"},{"name":"SAMSUNG Galaxy S10 plus"},{ "name":"SAMSUNG Galaxy S10e"},{"name":"SAMSUNG Galaxy S8"},{"name":"SAMSUNG Galaxy S8 Plus"},{"name":"SAMSUNG Galaxy S9"},{"名称":"三星 Galaxy S9 plus"}]}

所以我问自己在哪里放置.annotate(Min?或者我应该使用 queryset = Phone.objects.all() 创建一个ListCreateAPIView吗?是否可以在我的 serializers.py 中没有新字段的情况下显示min_price的数据?

标签: jsondjangodjango-modelsdjango-rest-frameworkdjango-views

解决方案


我已经在评论中提到了一些观点。但是,我要在这里重复一遍:(

1.如果你试图从 Price 模型中找到最小值,它不会返回预期的结果。因为,每一行只有一个price属性,因此Min(price)变成了price它自己

。2 . 如果你想序列化一个特定模型的查询集(比如Price),你应该在序列化器的元类中使用ModelSerializer定义的 with model=Price

3. 你不能Meta在一个序列化器中使用两个类。

4. 如果你想显示Min(price)对于api,它最适合Phone API


所以,

1. 删除Phone元类PriceSerializer

class PriceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Price
        fields = ('id', 'phone', 'price', 'date', 'market')

    phone = serializers.StringRelatedField()
    market = serializers.StringRelatedField()

我不确定您是否了解该StringRelatedField()机制,因为您没有__str__()对模型的方法做任何事情Price

2.创建一个新的序列化器类用于序列化查询Price

class PhoneSerializer(serializers.ModelSerializer):
    min_price = serializers.IntegerField()
    class Meta:
        model = Phone
        fields = '__all__'

添加一个新字段min_price以从查询集中捕获带注释的Min()值很重要。

3.新建视图类来显示Phone列表

class PhoneAPI(generics.ListAPIView):
    queryset = Phone.objects.annotate(min_price=Min('price__price'))
    serializer_class = PhoneSerializer

queryset属性必须是带注释的查询集。

4. 连接视图urls.py


推荐阅读