如何在 JSON 的 GET 请求中包含 Django 模型的外键列表?
How can I include in the JSON's GET request the list of foreign keys of a model in Django?
我的模型有可以拥有多个设备的用户。当我对用户执行 GET 请求时,它 returns 只有用户模型中指定的字段,这是应该的。但我希望该选项在 GET 请求返回的 JSON 中包含用户拥有的设备列表。我怎样才能做到这一点?其次,有没有办法有时可以让用户在相同 JSON 中获得设备列表,而其他时候却没有?另外,我真的是 Django 的新手,如果可能的话,我希望有很多代码示例可以更好地理解。
这些是我的模型:
class User(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField()
address = models.CharField(max_length=200)
class Device(models.Model):
description = models.CharField(max_length=200)
location = models.CharField(max_length=200)
max_energy_consumption = models.FloatField()
avg_energy_consuumption = models.FloatField()
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
我的序列化程序:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = '__all__'
以及以下用于 CRUD api 调用的默认 ModelViewSets:
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class DeviceViewSet(ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
有一些不同的方法,最简单的方法是在您的用户模型中添加一个 property
并将其添加到您的序列化程序中
class User(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField()
address = models.CharField(max_length=200)
@property
def devices(self):
return Device.objects.filter(user_id=self.id).values("location", "description").distinct()
class UserSerializer(serializers.ModelSerializer):
devices = serializers.ReadOnlyField()
class Meta:
model = User
fields = '__all__'
编辑 - 对于问题的第二部分:
我的经验是,当我们不需要所有信息(性能问题)时,在我们的序列化程序中编写 '__all__'
并不是最好的做法。为了解决这个问题,制作一个单独的序列化程序将再次成为一个简单的解决方案。每当我遇到这种事情时,我都会查询相同的端点,但会发送一个我不在其他端点中使用的不同 qs 在你的情况下,假设你的用户视图集路由类似于 /api/user/
你可以在发送你的时添加一个 qs向您的后端发出请求并添加 ?with_devices=true
。
然后你可以像这样使用你的第二个用户序列化器:
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
def get_serializer_class(self):
if self.request.GET.get("with_devices", False):
return UserWithDeviceSerializer
return UserSerializer
你的序列化器应该是这样的:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["name", "birth_date", ..so on]
class UserWithDeviceSerializer(serializers.ModelSerializer):
devices = serializers.ReadOnlyField()
class Meta:
model = User
fields = '__all__'
这将为您提供您在评论中提出的问题。
我的模型有可以拥有多个设备的用户。当我对用户执行 GET 请求时,它 returns 只有用户模型中指定的字段,这是应该的。但我希望该选项在 GET 请求返回的 JSON 中包含用户拥有的设备列表。我怎样才能做到这一点?其次,有没有办法有时可以让用户在相同 JSON 中获得设备列表,而其他时候却没有?另外,我真的是 Django 的新手,如果可能的话,我希望有很多代码示例可以更好地理解。
这些是我的模型:
class User(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField()
address = models.CharField(max_length=200)
class Device(models.Model):
description = models.CharField(max_length=200)
location = models.CharField(max_length=200)
max_energy_consumption = models.FloatField()
avg_energy_consuumption = models.FloatField()
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
我的序列化程序:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = '__all__'
以及以下用于 CRUD api 调用的默认 ModelViewSets:
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class DeviceViewSet(ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
有一些不同的方法,最简单的方法是在您的用户模型中添加一个 property
并将其添加到您的序列化程序中
class User(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField()
address = models.CharField(max_length=200)
@property
def devices(self):
return Device.objects.filter(user_id=self.id).values("location", "description").distinct()
class UserSerializer(serializers.ModelSerializer):
devices = serializers.ReadOnlyField()
class Meta:
model = User
fields = '__all__'
编辑 - 对于问题的第二部分:
我的经验是,当我们不需要所有信息(性能问题)时,在我们的序列化程序中编写 '__all__'
并不是最好的做法。为了解决这个问题,制作一个单独的序列化程序将再次成为一个简单的解决方案。每当我遇到这种事情时,我都会查询相同的端点,但会发送一个我不在其他端点中使用的不同 qs 在你的情况下,假设你的用户视图集路由类似于 /api/user/
你可以在发送你的时添加一个 qs向您的后端发出请求并添加 ?with_devices=true
。
然后你可以像这样使用你的第二个用户序列化器:
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
def get_serializer_class(self):
if self.request.GET.get("with_devices", False):
return UserWithDeviceSerializer
return UserSerializer
你的序列化器应该是这样的:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["name", "birth_date", ..so on]
class UserWithDeviceSerializer(serializers.ModelSerializer):
devices = serializers.ReadOnlyField()
class Meta:
model = User
fields = '__all__'
这将为您提供您在评论中提出的问题。