【问题标题】:Django Rest Framework foreign key serializationDjango Rest Framework 外键序列化
【发布时间】:2016-01-15 15:56:57
【问题描述】:

我有以下型号:

class Geofence(models.Model):
    id = models.IntegerField(default=0, primary_key=True)
    name = models.CharField(max_length=200, default="Geofence", blank=False)
    lat = models.DecimalField(default=0, decimal_places=6, max_digits=10, blank=False)
    long = models.DecimalField(default=0, decimal_places=6, max_digits=10, blank=False)
    radius = models.IntegerField(default=10, blank=False)

    def __str__(self):
        return "Geofence: " + str(self.name);

class Checkpoint(models.Model):
    id = models.IntegerField(default=0, primary_key=True)
    name = models.CharField(max_length=200, default="Geofence", blank=False)
    geofence = models.ForeignKey(Geofence, related_name='geofence')
    lat = models.DecimalField(default=0, decimal_places=6, max_digits=10, blank=False)
    long = models.DecimalField(default=0, decimal_places=6, max_digits=10, blank=False)
    trip_id = models.IntegerField(default=0, blank=False)
    enter_time = models.DateTimeField("Enter Time", blank=False)
    start_time = models.DateTimeField("Start Time", blank = True, null=True)
    stop_time = models.DateTimeField("Stop Time", blank= True, null = True)

及其各自的序列化程序:

class GeofenceSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(min_value=0)
    name = serializers.CharField()
    lat = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
    long = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
    radius = serializers.IntegerField(min_value=0)
    class Meta:
        model = Geofence
        fields = ('id', 'name','lat', 'long', 'radius')

    def create(self, valid_data):
        return Geofence.objects.create(**valid_data)

    def update(self, instance, valid_data):
        instance.id = valid_data.get('id', instance.id)
        instance.name = valid_data.get('name', instance.name)
        instance.name = valid_data.get('lat', instance.lat)
        instance.long = valid_data.get('long', instance.long)
        instance.radius = valid_data.get('radius', instance.radius)
        instance.save()



class CheckpointSerializer(serializers.ModelSerializer):
    lat = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
    long = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
    enter_time = serializers.DateTimeField()
    start_time =serializers.DateTimeField()
    geofence = serializers.SlugRelatedField(many=False, slug_field="id", read_only=True)
    class Meta:
        model = Checkpoint
        fields = ('trip_id', 'geofence', 'start_time', 'stop_time', 'lat', 'long', 'enter_time')

我从滑块中获取日期时间并进行 ajax 调用以获取相关数据。服务器以 500 错误响应。具体来说,错误“KeyError: geofence”

这是被调用的视图:

class ResultsView(APIView):
    model = Checkpoint
    serializer_class = CheckpointSerializer
    def get(self, request, start, end):
        begin_date = parse_datetime(request.GET["start"]) 
        end_date = parse_datetime(request.GET["end"])
        ids = Checkpoint.objects.filter(start_time__range=(begin_date,end_date)).filter(stop_time__range=(begin_date,end_date)).distinct().values('trip_id', 'lat', 'long', 'enter_time')
        serializer = CheckpointSerializer(ids, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        request.data["id"] = uuid.uuid4().int & (1<<8)-1
        serializer = CheckpointSerializer(data= request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.error)

和角度调用:

$http.get("http://127.0.0.1:8000/traffic/get/?end=" + $scope.endDateTime + "&format=json&search=Search&start=" + $scope.startDateTime)
  .then(function(response) {
     console.log("Response: " + response.data)
       $scope.data = response.data;
   });

我认为问题在于序列化程序中的外键:

geofence = serializers.SlugRelatedField(many=False, slug_field="id", read_only=True)

这是在 django rest 框架中序列化外键的正确方法吗?如果没有,有人能举个例子吗?

【问题讨论】:

    标签: django serialization django-rest-framework


    【解决方案1】:

    你是这个意思吗? Specifying nested serialization

    有一个简单的例子:

    class AccountSerializer(serializers.ModelSerializer):
        class Meta:
            model = Account
            depth = 1 # You need only add this sentence.
    

    结果是这样的:

    [
      {
        "id": 1,
        "priority": 10,
        "role": {
          "id": 1,
          "department": "researcher"
        }
      }
    ]
    

    但是,您可以获得 ForeignKey 的所有字段。 ForeignKey的一些字段我不知道怎么获取。

    【讨论】:

    • Depth = 1 对我有用。这扩展了所有相关模型。
    【解决方案2】:

    对于这个特定问题,我通过在字符字段中使用源参数来表示外键而不是相关字段来解决它。在这种情况下,正确的序列化程序条目是:

    geofence = serializers.CharField(source='geofence.id', read_only=True)
    
    class Meta:
        model = Checkpoint
        fields = ('geofence', 'start_time', 'lat', 'long', 'enter_time')
    

    我在检查点表中使用了它,因为检查点是地理围栏,而不是在原始帖子中错误地将外键放入地理围栏表中。字段名称简单地列在类元中。类元是必要的,因为序列化器是模型序列化器。

    【讨论】:

      【解决方案3】:

      我猜你必须做一些改变。您可以在 GeofenceSerializer 中引入许多 Checkpoint。这样:

      class GeofenceSerializer(serializers.ModelSerializer):
            id = serializers.IntegerField(min_value=0)
            name = serializers.CharField()
            lat = serializers.DecimalField(max_digits=10, decimal_places=6,     coerce_to_string=False)
            long = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
            radius = serializers.IntegerField(min_value=0)
            checkpoint = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
            class Meta:
                 model = Geofence
                fields = ('id', 'name','lat', 'long', 'radius','checkpoint')
      
      def create(self, valid_data):
          return Geofence.objects.create(**valid_data)
      
      def update(self, instance, valid_data):
          instance.id = valid_data.get('id', instance.id)
          instance.name = valid_data.get('name', instance.name)
          instance.name = valid_data.get('lat', instance.lat)
          instance.long = valid_data.get('long', instance.long)
          instance.radius = valid_data.get('radius', instance.radius)
          instance.save()
      
      
      
      class CheckpointSerializer(serializers.ModelSerializer):
            lat = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
            long = serializers.DecimalField(max_digits=10, decimal_places=6, coerce_to_string=False)
            enter_time = serializers.DateTimeField()
            start_time =serializers.DateTimeField()
      
            class Meta:
                 model = Checkpoint
                 fields = ('trip_id', 'start_time', 'stop_time', 'lat', 'long', 'enter_time') 
      

      【讨论】:

      • 说实话,我突然想到我的问题可能不是我最初认为的那样。然而,这很有帮助,我会将其标记为答案。
      猜你喜欢
      • 2015-01-07
      • 2017-10-05
      • 2013-06-21
      • 2019-01-19
      • 2018-06-07
      • 1970-01-01
      • 2016-04-10
      • 2021-04-09
      • 1970-01-01
      相关资源
      最近更新 更多