2

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
        }
        ...
        ...
    ]
     },
5
  • all of your Data you want create new is data = validated_data.pop('data')? I saw models.Data.objects.create(coin=coin, **data[0]) . Maybe issue is you use data[0]. try data in loop and create Commented Jan 14, 2019 at 9:18
  • thanks a lot for your concern.. but I dont think that loop would work because data[0] does same job that loop as data consists only one item.. as I think problem maight be that I dont understand what models.Data.objects.create(coin=coin, **data[0]) statement means explicitly.. especially coin=coin... if I assign coin, existing object of coin, would it be right ..?? thanks in advance.. Commented Jan 14, 2019 at 9:33
  • coin=coin mean in models.Data you will create, it will have this coin you created is FK. I saw expect result you have 2 different coin_id is "coin_id": 101 and "coin_id": 102. That mean this have 2 coin exists different in database. You want create 2 Data FK 2 Coin different? And can you show data in data[0] pls? Commented Jan 14, 2019 at 9:45
  • data = [{'date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0}] data[0] = {'date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0} Commented Jan 14, 2019 at 10:48
  • yes you noticed it correctlyy.. coin_id = 102 is not correct form it must be 101.. sorry thanks.. Commented Jan 14, 2019 at 11:04

3 Answers 3

3

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

Sign up to request clarification or add additional context in comments.

4 Comments

@GioSanikidze check the update and don't forget to upvote if it helps
God .. it was so easy.. thanks thanks thanks.... I spent more than week searching ways inside the box.. so I did it using data endpoint so .. problem is solved ..
@GioSanikidze You're welcome. Again, don't forget to upvote :)
You confirmed what I suspect was the correct approach. Thanks.
0

try change your input data with more than one item in array like example:

data = [{'date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0}, {'date': '2016-12-26', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0}]

This example have one more item in array data. And change this line:

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

to

coin = models.Coin.objects.create(**validated_data)
for item_data in data:
    models.Data.objects.create(coin=coin, **item_data)

This will create some Data with FK is Coin created.

Comments

0

This is how I did it.. Inside my viewset.ModelViewSet implementation In my case.. The parent class contains a list of manyToMany objects. Im posting new objects in the manyToMany..> Creating them.. then reinserting the IDs into the post data and calling the base class. Worked out pretty simple.. and I like it's contained in the view. Im newer to Django however.. but this worked for me.


class CaseDeepViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)

    queryset = Case.objects.all().order_by('-id')

    def get_serializer_class(self):
        if self.request.method in ['GET']:
            return CaseDeepSerializer
        return CaseSerializer

    def create(self, request):
        print('IM here: ')

        print(request.data)

        case_interactions = request.data.pop('new_case_interactions')
        listCreatedInteractions = []  
        for interaction in case_interactions:
            print("interaction", interaction)
            interaction['issara_staff'] = obj = IssaraUser.objects.get(pk=interaction.get('issara_staff'))
            listCreatedInteractions.append(CaseInteraction.objects.create(**interaction).id)

        request.data['case_interactions'] = listCreatedInteractions

        return super().create(request)   


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.