2017-09-13 61 views
1

我第一次使用DRF。我一直在阅读文档页面,但不知道如何做到这一点。Django-Rest-Framework - 嵌套对象和序列化器,如何?

我有两种模式,AdPrice模型引用广告模型。我需要列出广告的各种价格。

我的问题是:如何获得这样的广告列表?

[ 
    { 
    "title": "Some long title for Ad1", 
    "name": "Name Ad1", 
    "prices": { 
        { "name": "price now", "price": 200 }, 
        { "name": "price later", "price": 300 } 
       } 
    }, 
] 

models.py

class Ad(models.Model): 
    title = models.CharField(max_length=250) 
    name = models.CharField(max_length=100) 

    def __str__(self): 
     return self.name 

class AdPrice(models.Model): 
    ad = models.ForeignKey(Ad) 
    name = models.CharField(max_length=50) 
    price = models.DecimalField(max_digits=6, decimal_places=2) 

    def __str__(self): 
     return self.name 

serializers.py

class AdPriceSerializer(serializers.Serializer): 
    name = serializers.CharField(max_length=50) 
    price = serializers.DecimalField(max_digits=6, decimal_places=2) 

    class Meta: 
     model = AdPrice 

class AdSerializer(serializers.Serializer): 
    title = serializers.CharField(max_length=250) 
    name = serializers.CharField(max_length=100) 
    prices = AdPriceSerializer(many=True) 

views.py

class AdViewSet(viewsets.ModelViewSet): 
    """ 
    API endpoint that allows users to be viewed or edited. 
    """ 
    queryset = Ad.objects.all().order_by('-date_inserted') 
    serializer_class = AdSerializer 

当我尝试上面的代码,我得到这个错误:

AttributeError at /ads/ 

Got AttributeError when attempting to get a value for field `prices` on serializer `AdSerializer`. 
The serializer field might be named incorrectly and not match any attribute or key on the `Ad` instance. 
Original exception text was: 'Ad' object has no attribute 'prices'. 

如何解决这个问题的任何线索?

最好的问候, AndréLopes。

+0

您是否在'AdSerializer'上定义了类元? –

回答

2

从我所看到的在这里你缺少内

class AdSerializer(serializers.Serializer): 
    title = serializers.CharField(max_length=250) 
    name = serializers.CharField(max_length=100) 
    prices = AdPriceSerializer(many=True, read_only=True) 

    class Meta: 
     model = Ad 

read_only=Trueclass meta,为了也避免了N + 1个查询问题,你想覆盖queryset

from django.db.models import Prefetch

queryset=Ad.objects.all().order_by('-date_inserted').prefetch_related(Prefetch('adprice_set', queryset=AdPrice.objects.filter(ad_id__in=queryset), to_attr='prices')) 

由于Django的有慵懒的ORM,这意味着每个广告必须在疗法e,它会进行另一个查询以获取AdPrices。因此,对于100个广告,它会产生200个查询。不是最有效的解决方案,对吧?使用预取功能,您可以只需要两次查询即可完成,其中一个获取所有ads,另一个获取所有相关的adprices

+0

嗨Borko Kovacev。谢谢,你的代码工作。我用这个代码的问题是查询集,我更习惯于SQL。有可能使用RawQuery来获得相同的结果?非常感谢。 –

+1

@安德烈嘿安德烈!当然。 'queryset = Ad.objects.raw(原始SQL进入这里)'使用这个问题作为参考 - https://stackoverflow.com/questions/32159534/using-raw-sql-in-django-rest-framework –