2016-02-17 29 views
5

Tôi đang cố tạo một trình nối tiếp lồng nhau có thể ghi. Mô hình cha mẹ của tôi là Game và các mô hình lồng nhau là các phép đo. Tôi đang cố gắng đăng dữ liệu này vào ứng dụng DRF của tôi bằng cách sử dụng AJAX. Tuy nhiên, khi cố gắng đăng dữ liệu, các phép đo lồng nhau rỗng là OrderedDict().Django Rest Framework có thể ghi serializer lồng nhau với nhiều đối tượng lồng nhau

Dưới đây là mô hình của tôi:

class Game(models.Model): 
    start_timestamp = models.DateTimeField(auto_now_add=False) 
    end_timestamp = models.DateTimeField(auto_now_add=False) 
    date_added = models.DateTimeField(auto_now_add=True) 


class Measurement(models.Model): 
    game = models.ForeignKey(Game, on_delete=models.PROTECT, related_name='measurements') 
    measurement_type = models.CharField(max_length=56) 
    measurement = models.CharField(max_length=56) 
    timestamp = models.DateTimeField(auto_now_add=False) 
    date_added = models.DateTimeField(auto_now_add=True) 

Dưới đây là serializers tôi:

class MeasurementSerializer(serializers.ModelSerializer): 
     timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601']), required=False) 

     class Meta: 
      model = Measurement 
      fields = ('measurement_type', 'measurement', 'timestamp') 


class GameSerializer(serializers.ModelSerializer): 
    start_timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601'])) 
    end_timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601'])) 
    measurements = MeasurementSerializer(many=True) 

    class Meta: 
     model = Game 
     fields = ('id', 'start_timestamp', 'end_timestamp', 'measurements') 

    def create(self, validated_data): 
     measurements = validated_data.pop('measurements') 
     game = Game.objects.create(**validated_data) 
     for measurement in measurements: 
      Measurement.objects.create(game=game, **measurement) 
     return game 

Quan điểm của tôi cho trò chơi như sau:

class GameList(generics.ListCreateAPIView): 
    queryset = Game.objects.all() 
    serializer_class = GameSerializer 

Tôi đi theo this tutorial cho cấu trúc.

Tôi cố gắng để gửi đến API này qua AJAX, mã bên dưới:

$.ajax({ 
     url: base_url + '/games/', 
     dataType: "json", 
     data: { 
       "start_timestamp": "2016-02-16 14:51:43.000000", 
       "end_timestamp": "2016-02-16 14:53:43.000000", 
       "measurements":[ 
        {'measurement_type':'type1', 'measurement':'71', 'timestamp':'2016-02-16 14:53:43.000000'}, 
        {'measurement_type':'type1', 'measurement':'72', 'timestamp':'2016-02-16 14:54:43.000000'}, 
        {'measurement_type':'type1', 'measurement':'73', 'timestamp':'2016-02-16 14:55:43.000000'}, 
       ] 
       }, 
     type: 'POST' 
    }) 
    .error(function(r){}) 
    .success(function(data){}) 
}); 

On đăng dữ liệu này, tôi thấy trong phương pháp tạo trong GameSerializer rằng validate_data.pop ('đo') chứa danh sách gồm 3 bộ từ điển được đặt hàng (OrderedDict()) rỗng.

UPDATE: Tôi đã tìm thấy rằng các initial_data sắp tới trong qua request.data được cấu trúc như sau:

'emotion_measurements[0][measurement_type]' (4397175560) = {list} ['type1'] 
'emotion_measurements[0][measurement]' (4397285512) = {list} ['71'] 
'emotion_measurements[0][timestamp]' (4397285600) = {list} ['2016-02-16 14:53:43.000000'] 
'emotion_measurements[1][measurement_type]' (4397175040) = {list} ['type1'] 
'emotion_measurements[1][measurement]' (4397285864) = {list} ['72'] 
'emotion_measurements[1][timestamp]' (4397285952) = {list} ['2016-02-16 14:54:43.000000'] 
'emotion_measurements[2][measurement_type]' (4397175040) = {list} ['type1'] 
'emotion_measurements[2][measurement]' (4397285864) = {list} ['73'] 
'emotion_measurements[2][timestamp]' (4397285952) = {list} ['2016-02-16 14:55:43.000000'] 

Có ai gặp phải vấn đề này trước đây chưa? Cảm ơn!

CẬP NHẬT # 2

tôi đã có thể giải quyết này (mặc dù tôi tin rằng nó là nhiều hơn một workaround hơn một giải pháp) bằng cách thêm dòng sau vào MeasurementSerializer tôi:

def to_internal_value(self, data): 
     formatted_data = json.dumps(data) 
     formatted_data = formatted_data.replace("[", "").replace("]","") 
     formatted_data = json.loads(formatted_data) 
     return formatted_data 

Dữ liệu đo lường đến trong một QueryDict khi tôi tin rằng tôi cần một Dict. Ngoài ra còn có một số dấu ngoặc phụ xung quanh khóa và giá trị vì vậy tôi cũng phải loại bỏ các dấu ngoặc đó.

Vẫn đang tìm kiếm câu trả lời hay hơn thế này!

+1

Bạn có thể kiểm tra những gì trong 'self.initial_data.get ('measurement')'? Và ngoài ra, chỉ để được an toàn: kiểm tra xem máy chủ của bạn đã nhận được JSON gì. (Mã AJAX của bạn có vẻ ổn và chắc chắn nhất đến máy chủ như dự định - nhưng tốt ...) – Risadinha

+0

Chỉ nghĩ rằng tôi có thể tìm thấy sau khi xem mã của bạn nhiều lần là có thể (có thể!) Dấu thời gian của bạn không phân tích cú pháp theo cho mẫu của bạn. Tôi không thể tìm thấy bất cứ điều gì khác, cũng so sánh với serializers của riêng tôi và ví dụ DRF. Vì dấu thời gian là tùy chọn, có thể kiểm tra nó mà không có các giá trị này, chỉ để đảm bảo.Nhưng nếu đó là vấn đề, câu hỏi sẽ là lý do tại sao bạn không nhìn thấy lỗi xác nhận. – Risadinha

+0

@Risadinha Tôi đã cập nhật cấu trúc ban đầu. Cấu trúc là một QueryDict, mà tôi không quá quen thuộc với. Tôi cũng có cùng một dấu thời gian suy nghĩ không cần thiết trong trường hợp đó là vấn đề định dạng ngày tháng nhưng vẫn là vấn đề tương tự. –

Trả lời

0

Vấn đề ở đây là ở mặt trước. Theo mặc định, máy chủ giải thích các dữ liệu như application/x-www-form-urlencoded và để cho nó hiểu rằng bạn đang gửi nó một json, bạn cần phải xác định contentType trong yêu cầu $.ajax của bạn:

$.ajax({ 
    url: base_url + '/games/', 
    dataType: "json", 
    data: {...}, 
    contentType: 'application/json; charset=UTF-8', // add this line 
    type: 'POST' 
}) 
.error(function(r){}) 
.success(function(data){}); 

Bây giờ bạn validated_data.pop('measurements') trong create() phương pháp của bạn GameSerializer sẽ tạo ba đối tượng với measurements của bạn (nhưng đừng quên làm lại cách giải quyết của bạn từ Cập nhật # 2).

Các vấn đề liên quan