I'm writing a django-rest-framework backend with rest-framework-mongoengine. So far I have schemas for 2 types - for User and for Device(Box). Sources as follows:
models.py:
from __future__ import unicode_literals
import datetime
from mongoengine import Document, connect, EmbeddedDocument, fields, DynamicDocument
from django.db import models
# Create your models here.
from mongoengine import signals
connect('yourdb', alias='default')
class GPS(EmbeddedDocument):
lat = fields.FloatField(null=False, required=True)
lon = fields.FloatField(null=False, required=True)
class PPM(EmbeddedDocument):
time = fields.DateTimeField(default=datetime.datetime.now())
value = fields.IntField(null=False, required=True)
@classmethod
def pre_save(cls, sender, document, **kwargs):
document.time = datetime.datetime.now()
signals.pre_save.connect(PPM.pre_save, sender=PPM)
class BuyHistory(EmbeddedDocument):
time = fields.DateTimeField(default=datetime.datetime.now())
boxid = fields.StringField(max_length=128, null=False, required=True)
username = fields.StringField(max_length=128, null=False, required=True)
product = fields.StringField(max_length=128, null=False, required=True)
amount = fields.IntField()
@classmethod
def pre_save(cls, sender, document, **kwargs):
document.time = datetime.datetime.now()
signals.pre_save.connect(BuyHistory.pre_save, sender=BuyHistory)
class RecycleHistory(EmbeddedDocument):
time = fields.DateTimeField(default=datetime.datetime.now())
boxid = fields.StringField(max_length=128, null=False, required=True)
username = fields.StringField(max_length=128, null=False, required=True)
amount = fields.IntField()
@classmethod
def pre_save(cls, sender, document, **kwargs):
document.time = datetime.datetime.now()
signals.pre_save.connect(RecycleHistory.pre_save, sender=RecycleHistory)
class Box(Document):
boxid = fields.StringField(max_length=128, null=False, required=True)
gps = fields.EmbeddedDocumentField(GPS, required=True)
buy_history = fields.EmbeddedDocumentListField(BuyHistory, default='[]')
recycle_history = fields.EmbeddedDocumentListField(RecycleHistory, default='[]')
ppm_history = fields.EmbeddedDocumentListField(PPM, default='[]')
class User(Document):
username = fields.StringField(max_length=128, null=False, required=True)
rfid = fields.StringField(max_length=32, null=False, required=True)
buy_history = fields.EmbeddedDocumentListField(BuyHistory)
recycle_history = fields.EmbeddedDocumentListField(RecycleHistory)
serializers.py:
from rest_framework_mongoengine import serializers
from models import User, BuyHistory, Box, RecycleHistory, PPM
class UserSerializer(serializers.DocumentSerializer):
class Meta:
model = User
fields = ('username', 'rfid', 'buy_history', 'recycle_history')
class PPMSerializer(serializers.DocumentSerializer):
class Meta:
model = PPM
fields = ('time', 'value')
class BuyHistorySerializer(serializers.EmbeddedDocumentSerializer):
class Meta:
model = BuyHistory
fields = ('time', 'boxid', 'username', 'product', 'amount')
class RecycleHistorySerializer(serializers.EmbeddedDocumentSerializer):
class Meta:
model = RecycleHistory
fields = ('time', 'boxid', 'username', 'product', 'amount')
class BoxSerializer(serializers.DocumentSerializer):
class Meta:
model = Box
fields = ('id', 'boxid', 'gps', 'buy_history', 'recycle_history', 'ppm_history')
def update(self, instance, validated_data):
buy = validated_data.pop('buy_history')
recycle = validated_data.pop('recycle_history')
ppm = validated_data.pop('ppm_history')
updated_instance = super(BoxSerializer, self).update(instance, validated_data)
for buy_data in buy:
updated_instance.buy_history.append(BuyHistory(**buy_data))
for recycle_data in recycle:
updated_instance.recycle_history.append(RecycleHistory(**recycle_data))
for ppm_data in ppm:
updated_instance.ppm_history.append(PPM(**ppm_data))
updated_instance.save()
return updated_instance
My goal is to update user's buy_history
and recycle_history
when updating the Box
object. How can I do it?
Ok, I have found a solution, apparently it was super simple but if someone has similar confusion here's the answer:
Just get the user
with username
which is set in nested object like this.
for buy_data in buy:
buy_history_s = BuyHistory(**buy_data)
try:
user = User.objects.get(username=buy_history_s.username)
except errors.DoesNotExist:
raise exceptions.AuthenticationFailed()
if buy_history_s.time is None:
buy_history_s.time = datetime.datetime.now()
updated_instance.buy_history.append(buy_history_s)
user.buy_history.append(buy_history_s)
user.save()
Cheers