Search code examples
django-rest-frameworkdjongo

Using django rest framework, how to add new nested child object for existing parent object


I am trying to build a data storage for time series data, for this I have created nested objects Coin and Data, where Coin is parent object and contains Data entries that each data entry is individual object. at this moment my code creates nested object Coin[Data] as I build create function within CoinSerializer, but I could not use proper method to add/create child object within existing Coin object

In my python virtual environment I've been using django 2.1.4 drf 3.9 and python 3.6.. also as a backend db engine for my project I got mongodb and use djongo 1.2 to maintain it

Any suggested idea or way for my problem would be greatly appreciated, as its my first post ever and sorry for any Inappropriate style..

models.py

class Coin(models.Model):
    coin_name = models.CharField(max_length=100,blank=True)


class Data(models.Model):
    coin = models.ForeignKey(Coin, related_name='data', on_delete=models.CASCADE,blank=True)
    date = models.DateField(("Date"),blank=True)
    open = models.FloatField(null=True, blank=True)
    high = models.FloatField(null=True, blank=True)
    low = models.FloatField(null=True, blank=True)
    close = models.FloatField(null=True, blank=True)

    class Meta:
        unique_together = ('coin', 'date',)
        ordering = ['date']

    def __unicode__(self):
        return '%d: %d %d %d %d' % (self.date, self.open, self.high, 
self.low, self.close)

serializers.py

class DataSerializer(serializers.ModelSerializer):
class Meta():
    model = models.Data
    fields = ('coin_id','pk','id','date','open','high','low','close')

class CoinSerializer(serializers.ModelSerializer): data = DataSerializer(many=True)

class Meta:
    model = models.Coin
    fields = ('pk','id','coin_name', 'data')

def create(self, validated_data):

    data = validated_data.pop('data')
    coin = models.Coin.objects.create(**validated_data)
    models.Data.objects.create(coin=coin, **data[0])

    return coin

my result is kind of this

 {
    "pk": 101,
    "id": 101,
    "coin_name": "ripple",
    "data": [
        {
            "coin_id": 101,
            "pk": 56,
            "id": 56,
            "date": "2016-12-25",
            "open": 4036.0,
            "high": 4101.0,
            "low": 3983.0,
            "close": 4065.0
        }
    ]
     },

and expect to consist lots of data objects which I will add by the time in existing coin object

 {
    "pk": 101,
    "id": 101,
    "coin_name": "ripple",
    "data": [
        {
            "coin_id": 101,
            "pk": 56,
            "id": 56,
            "date": "2016-12-25",
            "open": 4036.0,
            "high": 4101.0,
            "low": 3983.0,
            "close": 4065.0
        }
        {
            "coin_id": 102,
            "pk": 57,
            "id": 57,
            "date": "2016-12-26",
            "open": 4065.0,
            "high": 4189.0,
            "low": 3967.0,
            "close": 4075.0
        }
        ...
        ...
    ]
     },

Solution

  • You're going about it the wrong way. You should instead make another endpoint for Data too. There you can create data and pass the id of the parent coin. Using the nested architecture is only meaningfull when you're creating both the coin and the data at the same time. In this case, just use a data endpoint to create data while passing the id of the coin

    EDIT: BULK CREATE

    And just to throw a little light on how to implement bulk create for several Data objects - you will need to imlement it using a loop as model.objects.create() excpects data for a single object. You could use bulk_create but it has a lot of caveats, so I would use a loop