2

私はrest-framework-mongoengineでdjango-rest-frameworkバックエンドを書いています。今まで私はUserとDevice(Box)の2種類のスキーマを持っていました。ソースを次のように複数のデータベーステーブルを1つのPUT/PATCHに更新する

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 

私の目標は、更新することで、ユーザのbuy_historyrecycle_historyBoxオブジェクトを更新。どうしたらいいですか?

ただ、このようなネストされたオブジェクトに設定されているusernameuserを得る:

+0

とDOデータベースが絵の中に来るのか? – e4c5

+0

タイトルを変更するショットをより適切なものにする –

+1

Kostya、 'RecycleHistory'、' BuyHistory'などの 'EmbeddedDocuments'のための' EmbeddedDocumentSerializers'を手動で作成するべきではありません - トップレベルの 'DocumentSerializer'はそれらを自動的に生成します。 'pre_save'シグナルが' EmbeddedDocument'sに適用できるかどうかは分かりません。トップレベルのドキュメントでは 'embedded()'を呼び出すため、埋め込まれたサブソンではありません。 –

答えて

0

[OK]を、私は明らかにそれが超簡単だった誰かが同様の混乱を持っている場合、ここでの答えですが、解決策を発見しました。

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() 

乾杯

+0

誰かが 'AuthenticationFailed()'よりも優れた例外を知っていれば、 –

関連する問題