2017-09-13 99 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 –