在Django REST框架中,如何访问外键引用的表中的字段

时间:2016-03-16 20:17:51

标签: django python-2.7 django-rest-framework

我在Django中有以下模型:

class campaign(models.Model):
    start_date = models.DateField('Start Date')
    end_date = models.DateField('End Date')
    description = models.CharField(max_length=500)
    name = models.CharField(max_length=200)
    active_start_time = models.TimeField()
    active_end_time = models.TimeField()
    last_updated = models.DateTimeField('Date updated',auto_now=True)
    active = models.BooleanField(default=True)
    client_id = models.ForeignKey('client',on_delete=models.PROTECT)
    def __unicode__(self):
            return u'%d | %s | %s' % (self.id,self.name, self.description)

class campaign_product(models.Model):
    product_id = models.ForeignKey('product',on_delete=models.PROTECT)
    last_updated = models.DateTimeField('Date updated',auto_now=True)
    campaign_id = models.ForeignKey('campaign',on_delete=models.PROTECT)

class product(models.Model):
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=500)
    sku = models.CharField(max_length=200,blank=True,null=True)
    retail_price = models.DecimalField(decimal_places=2,max_digits=11)
    discount_price = ((1,'Yes'),(0,'No'))
    discounted_price = models.DecimalField(decimal_places=2,max_digits=11,blank=True,null=True)
    category_id = models.ForeignKey('category',on_delete=models.PROTECT)
    last_updated = models.DateTimeField('Date updated',auto_now=True)
    active = models.BooleanField(default=True)
    def __unicode__(self):
        return u'%d | %s' % (self.id, self.name)

我还有以下序列化程序:

class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = campaign_product
        fields = ('product_id', 'campaign_id')

以下视图在urls.py文件中设置行为:

class campaignProductViewSet(viewsets.ModelViewSet):
    queryset = campaign_product.objects.filter(campaign_id__start_date__lte=datetime.now(),campaign_id__end_date__gte=datetime.now(),campaign_id__active__exact=True)
    serializer_class = campaignProductSerializer

我的问题是我需要在我的查询结果中包含产品模型中的名称字段,例如在http://127.0.0.1:8000/campaign_product/1/上发出请求时。 Currenly此请求仅返回product_id和campaign_id。我尝试按如下方式制作序列化器:

class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = campaign_product
        fields = ('product_id', 'campaign_id', 'product.name')

但是服务会返回以下错误:

Field name `product.name` is not valid for model `campaign_product`.

我尝试使用带有和不带引号的product__name。它没有引号,它告诉我没有这样的变量,并且使用引号它给出的模型错误无效,类似于上面的。 Heeelp!获得这个额外的领域被证明是一种痛苦: - (

1 个答案:

答案 0 :(得分:4)

你想要的东西需要看起来像这样:

class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
    product_name = serializers.CharField(source='product_id.name')

    class Meta:
        model = campaign_product
        fields = ('product_id', 'campaign_id', 'product_name')

P.S。作为一个不相关的附注,Python代码中的一般约定是使用CamelCase命名类,例如CampaignCampaignProductProductCampaignProductSerializer

编辑: P.P.S.最初,我用product_name写了source='product.name'字段。这实际上是由于我过快地查看代码并根据Django约定做出假设。通常,使用Django ForeignKey,您可以在链接到的模型之后命名ForeignKey字段,而不是使用_id明确命名它。例如,CampaignProduct模型通常会使用product = ForeignKey(...)campaign = ForeignKey(...)编写。在后台,Django实际上将使用product_idcampaign_id作为数据库字段名称。您还可以在模型实例上访问这些名称。但是模型实例上的productcampaign变量实际上会返回您引用的对象。希望一切都有意义。