Django Rest框架外键序列化
我有以下型号:Django Rest框架外键序列化,django,serialization,django-rest-framework,Django,Serialization,Django Rest Framework,我有以下型号: 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, bla
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)
我认为问题在于序列化程序中的外键:
geofence = serializers.SlugRelatedField(many=False, slug_field="id", read_only=True)
这是在django rest框架中序列化外键的正确方法吗?如果没有,有人能举个例子吗?我想你必须做一些改变。您可以在GeofenceSerializer中引入许多检查点。这样:
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')
对于这个特殊问题,我通过在字符字段中使用源参数来表示外键,而不是相关字段来解决它。在这种情况下,正确的序列化程序条目是:
geofence = serializers.CharField(source='geofence.id', read_only=True)
class Meta:
model = Checkpoint
fields = ('geofence', 'start_time', 'lat', 'long', 'enter_time')
我在Checkpoint表中使用它,因为Checkpoint是一个地理围栏,而不是将外键错误地放在原始post的地理围栏表中。字段名仅列在meta类中。类元是必需的,因为序列化程序是模型序列化程序。您的意思是
有一个简单的例子:
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适合我。这扩展了所有相关模型。
[
{
"id": 1,
"priority": 10,
"role": {
"id": 1,
"department": "researcher"
}
}
]