2017-02-21 198 views
2

我正在研究Django中的CRUD API,我需要序列化两个表中的外键模型。这个模型在两个一对多关系上有很多方面,我真的没有看到在这个模型中指定关系的其他方式(我是python和Django的新手,我正在使用Django-Rest-Framework创建API)DRF - 使用多个外键序列化模型

所以,我有两个问题:

1 - Is it a good Idea to have multiple foreign keys in my model or I should refractor my relationships some other way?

2 - If it is fine to have multiple foreign keys in a single model, how do I serialize the model to return the proper JSON?

我的模型是这样的(多带几个字段):

class DataSource(models.Model): 
    datasource_name = models.CharField(max_length=50, unique=True) 
    datasource_description = models.CharField(max_length=100) 
    ... 

class Campaign(models.Model): 
    name = models.CharField(max_length=200) 
    subject = models.CharField(max_length=200) 
    sender = models.EmailField(max_length=200) 
    ... 

class CampaignDeliveries(models.Model): 
    campaign_id = models.ForeignKey(Campaign) 
    datasource_id = models.ForeignKey(DataSource) 
    delivery_reference_id = models.CharField(max_length=200, primary_key=True) 
    date_sent = models.DateTimeField() 

交货记录提供了交货的活动以及为该交货选择的数据源。

数据必须以格式返回,如:

{ 
    campaign_id: 001, 
    datasource_id: 002, 
    datasource_name: "Data Source Name", 
    campaign_name: "Campaign Name" 
    setup_date:"<Setup Date>", 
    delivery_history:[{ 
     delivery_reference_id:DL_001, 
     sender : "[email protected]", 
     subject : "Subject", 
     sent_on : "<Date>" 
    }, 
    { 
     delivery_reference_id:DL_002, 
     sender : "[email protected]", 
     subject : "Subject", 
     sent_on : "<Date>" 
    }, 
    { 
     delivery_reference_id:DL_003, 
     sender : "[email protected]", 
     subject : "Subject", 
     sent_on : "<Date>" 
    } 
    .... 
    ] 
} 

datasource_idcampaign_id场均Django在该记录中的默认的ID被创造而delivery_reference_id是定制的ID被分配而同时创建交付记录。

我希望我已经说清楚了。但是,请问是否有不清楚的地方。

+0

试试这个:http://www.django-rest-framework.org/api-guide/relations/#nested-relationships – Amar

+0

你在查询什么来获取数据。您可以分享填充的模型delivery_history –

+0

您使用DRF的框架是什么? – marin

回答

0

通常你的名字,像这样的ForeignKey领域:

class CampaignDelivery(models.Model): 
    campaign = models.ForeignKey('Campaign') 

字段campaign_id是自动添加的,并且是存储广告系列ID的表格字段的参考。我可以经常使用。所以CampaignDelivery.campaign返回django对象,CampaignDelivery.campaign_id返回引用的广告系列的ID。

在一个模型中有多个外键没有错,但我不确定你想在这里完成什么。我认为你需要获得Campaign数据及其交付历史。 您提供的响应示例对此不太好,因为这意味着可以将一次投放分配给多个广告系列(因为您有ForeignKey,所以不是这样)。你可以做到这一点是这样的:

from rest_framework import serializers 

class CampaignDeliverySerializer(serializers.ModelSerializer): 

    class Meta: 
     model = CampaignDelivery 
     fields = ('date_sent', 'datasource_id', 'delivery_reference_id', 'datasource__datasource_name', ...) 

class CampaignSerializer(serialziers.ModelSerializer): 
    delivery_history = CampaignDeliverySerializer(
          source='campaigndeliveries_set', 
          many=True 
         ) 

    class Meta: 
     model = Campaign 
     fields = ('id', 'name', 'sender', 'subject', 'delivery_history', ...) 

回应示例:

{ 
    'campaign': { 
     'id': 123, 
     'name': 'Best campaign name evar', 
     'sender': '[email protected]', 
     'subject': 'Campaign subject', 
     'delivery_history': [ 
      { 
       'date_sent': '2017-02-22', 
       'datasource_id': 321, 
       'delivery_reference_id': 'DL_001', 
       'datasource__datasource_name': 'Datasource name' 
      }, 
      ... 
     ] 
    } 
} 
+0

投放可以包含广告系列和数据源的任意组合。这就是为什么我有两个外键。 –

+0

使样本响应更有意义。谢谢 :) –

0

1)这是你的意见如何FK模型上自己的逻辑,但在这个例子中,我的方式来做到这一点。

2)这里是答案:

由默认必须命名为每FK related_name的主力机型。

models.py

class CampaignDeliveries(models.Model): 
    delivery_reference_id = models.CharField(max_length=200, primary_key=True) 
    date_sent = models.DateTimeField() 


class DataSource(models.Model): 
    datasource_name = models.CharField(max_length=50, unique=True) 
    datasource_description = models.CharField(max_length=100) 
    campain_id = models.ForeignKey(CampaignDeliveries, related_name='data_source') 

class Campaign(models.Model): 
    name = models.CharField(max_length=200) 
    subject = models.CharField(max_length=200) 
    sender = models.EmailField(max_length=200) 
    campain_id = models.ForeignKey(CampaignDeliveries, related_name='campaign_source') 

serialiers.py

class DataSourceSerilaizer(serializers.ModelSerializer) 

    class Meta: 
     model = DataSource 
     fileds = '__all__' 


class CampaignSerilaizer(serializers.ModelSerializer) 

    class Meta: 
     model = Campaign 
     fileds = '__all__' 


class CampaignDeliveriesSerilaizer(serializers.ModelSerializer): 

    campaign_source = CampaignSerilaizer(many=True) 
    data_source = DataSourceSerilaizer(many=True) 

    class Meta: 
     model = CampaignDeliveries 
     fileds = '__all__' 

viwes.py

qv = CampaignDeliveries.objects.all() 
serializer = CampaignDeliveriesSerilaizer(qv) 
print (serializer.data) 
+0

NOOOO!你已经使模型和序列化器完全相反,他们应该是 –

+0

YEAAAAAAA!你现在可以用不同的方式思考。 – marin

+0

但是,我的数据源并未绑定到单个广告系列投放,并且单个数据源可能会用于多个广告系列投放 –