2016-12-08 57 views
1

我有一個設置,我需要爲現有的javascript數據模型編寫一個API,我不想觸及(現在)。 javascript數據具有與我想在服務器上不同的體系結構。所以我的目標是將數據發送到API時,將從JavaScript獲得的數據轉換爲適合我的數據庫模型。當從API請求數據時,它應該匹配javascript的預期數據模型。Django rest將平面數據轉換爲串行器中的關係數據

我不知道我是否可以用ModelSerializers來做到這一點,如果是的話,那麼數據轉換的正確位置在哪裏?在視圖中?在序列化程序中。

我的設置是像這樣:

//javascript structure 
{ 
    scores: [ 
    { 
     id: 12, 
     points: 2 
     maxpoints: 12 
     siteuxid: 'EXAMPLE' 
    }, 
    { ... } 
    ] 
} 

//More models in django 
{ 
    scores: [ 
    { 
     id: 12, 
     points: 2, 
     question: { 
     id: 12, 
     maxpoints: 12, 
     siteuxid: 'EXAMPLE' 
     } 
    }, 
    ] 
} 

是否有任何的例子任何人都可以指向我,那achive一樣嗎?基本上它是關於在服務器和客戶端有不同的數據結構並使它們兼容。 Googleing沒有幫助。

編輯: 我的第一個問題是,我沒有得到我的串行器中的所有發佈的數據。當我發佈

{ 
    "scores": [{"id":"QFELD_1.1.3.QF2","siteuxid":"VBKM01_VariablenTerme","section":1,"maxpoints":4,"intest":false,"uxid":"ER2","points":0,"value":0,"rawinput":"363"}] 
} 

class UserDataSerializer(serializers.ModelSerializer): 
    scores = ScoreSerializer(many=True, required=False) 

    def create(self, validated_data): 
     print('userDataSerializer validated_data', validated_data) 
     ... 

class ScoreSerializer(serializers.ModelSerializer): 
    id = serializers.CharField(required=False, allow_blank=True, max_length=100) 
    question = QuestionSerializer(required=False) 

    class Meta: 
     model = Score 
     fields = ('id', 'question', 'points', 'value', 'rawinput', 'state') 

我只得到輸出

userDataSerializer validated_data {'scores': [OrderedDict([('id', 'QFELD_1.1.3.QF2'), ('points', 0), ('value', 0), ('rawinput', '363')])]} 

沒有score.maxpoints等(因爲它不是在串行,但我怎麼可以添加它要驗證數據以便從UserDataSerializer中的發佈數據創建適當的問題對象)

+0

這通常會進入序列化程序,並且DRF文檔至少應該讓您開始。除非存在非平凡的業務邏輯 - 在這種情況下,您可能需要創建一個由ModelSerializer序列化的適配器或代理模型,並且可以保存/更新其對應的常規模型。如果您需要幫助,則必須提供有關業務邏輯的更多詳細信息。 – Risadinha

+0

已更新,向您展示更多我的代碼 – niklas

+0

序列化程序當然只會返回'Meta'中指定字段的值。將缺少的字段添加到'Meta.fields'並添加必要的方法來驗證和轉換序列化程序中的字段 - 或者在視圖中進行,如果您願意的話。雖然如果你只支持這種格式,那麼這就是你的序列化程序應該做的事情 - 這是傳入數據和內部數據結構之間的抽象層。 – Risadinha

回答

1

答案是肯定的,您將使用視圖來修改您的輸入數據,因爲您必須在視圖將數據發送到序列化程序之前對數據進行這些調整。這是由於同樣的原因,您只能在驗證的數據中看到序列化程序的屬性 - 序列化程序會忽略它無法識別的所有屬性。

因此,首先,在您的視圖的post方法中更改request.data以使其按您的需要構造。

def post(self, request, *args, **kwargs): 
    request.data['question'] = { 
     'maxpoints': request.data.pop('maxpoints'), 
     'siteuxid': request.data.pop('siteuxid'), 
    } 

這應該是您開始所需的一切。

但是請注意,在您的示例中,questionid: 12這很奇怪。如果您嘗試創建一個question對象以及您的score對象,則它應該沒有id。但如果問題是現有的對象,則不應該發送字典,而只能使用id

例如,您應該在輸入中發送question: 1。 DRF的ModelSerializer足夠聰明,可以知道您試圖保存的scoreid = 1question有關。當你在它的時候,檢查序列化器的validated_data,你會看到question的例子id = 1。魔法!