2017-02-21 14 views
2

Я работаю над API CRUD в Django, и мне нужно сериализовать модель, которая имеет внешние ключи в двух таблицах. Модель находится на стороне «много» на двух отношениях «один ко многим», и я не вижу другого способа определения отношений в этой модели (я новичок в 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_id и campaign_id поля являются идентификатор по умолчанию задается Джанго к записям в то время как они были созданы и delivery_reference_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 добавляется автоматически и является ссылкой на поле таблицы, в котором хранится идентификатор кампании. Я могу быть полезен довольно часто. Таким образом, CampaignDelivery.campaign возвращает объект django и CampaignDelivery.campaign_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) Вот ответ:

По умолчанию вы должны назвать related_name для каждого FK к основной модели.

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

Но мой источник данных не привязан к одной доставке кампании, и один источник данных может использоваться в нескольких кампаниях доставки –

 Смежные вопросы

  • Нет связанных вопросов^_^