[英]Django REST API query on related field
我有 3 个模型,Run、RunParameter、RunValue:
class Run(models.Model):
start_time = models.DateTimeField(db_index=True)
end_time = models.DateTimeField()
class RunParameter(models.Model):
parameter = models.ForeignKey(Parameter, on_delete=models.CASCADE)
class RunValue(models.Model):
run = models.ForeignKey(Run, on_delete=models.CASCADE)
run_parameter = models.ForeignKey(RunParameter, on_delete=models.CASCADE)
value = models.FloatField(default=0)
class Meta:
unique_together=(('run','run_parameter'),)
Run可以有一个RunValue ,它是一个浮点值,其值的名称来自RunParameter (基本上是一个包含名称的表),例如:
RunValue可以是AverageTime或MaximumTemperature
然后, Run可以具有RunValue = RunParameter:AverageTime值 X。
另一个Run实例可能具有RunValue = RunParameter:MaximumTemperature值 Y 等。
我创建了一个端点来查询我的 API,但我只有RunParameter ID(因为您可以通过 select 直接绘制哪个参数),而不是RunValue ID。 我基本上显示了所有RunParameter的列表和所有Run实例的列表,因为如果我显示了RunValue的所有实例,那么该列表将太长且令人困惑,因为您不会看到“最高温度”,而是会看到:
“运行 X 的最高温度”
“运行 Y 的最高温度”
“运行 Z 的最高温度”等(重复 50 次以上)。
我的 API 视图如下所示:
class RunValuesDetailAPIView(RetrieveAPIView):
queryset = RunValue.objects.all()
serializer_class = RunValuesDetailSerializer
permission_classes = [IsOwnerOrReadOnly]]
其序列化程序如下所示:
class RunValuesDetailSerializer(ModelSerializer):
run = SerializerMethodField()
class Meta:
model = RunValue
fields = [
'id',
'run',
'run_parameter',
'value'
]
def get_run(self, obj):
return str(obj.run)
还有 URL 以防万一:
url(r'^run-values/(?P<pk>\d+)/$', RunValuesDetailAPIView.as_view(), name='values_list_detail'),
Since I'm new to REST API, so far I've only dealt with having the ID of the model API view I am querying directly, but never an ID of a related field. 我不确定在哪里修改我的查询集以将其传递给 ID 以从相关字段中获取适当的 model 实例。
在我进行 API 查询时,我有Run instance ID 和RunParameter ID。 我需要查询集是:
run_value = RunValue.objects.get(run=run_id, run_parameter_id=param_id)
到目前为止,我只需要做类似的事情:
run_value = RunValue.objects.get(id=value_id) # I don't have this ID
如果我理解正确,您正在尝试获取只有Run
id 和RunParameter
id 的RunValue
实例,即基于相关字段的查询。
查询集可以通过以下方式实现:
run_value = RunValue.objects.get(
run__id=run_id,
run_parameter__id=run_parameter_id
)
假设一个RunValue
实例只有 1 个相关的Run
和RunParameter
,这将返回您所追求的RunValue
实例。
如果这不是你的意思,请告诉我。
双下划线允许您访问查询中的相关实例字段。
好吧,它非常简单,您所要做的就是覆盖get_object
方法,例如(从文档中复制粘贴):
# view
from django.shortcuts import get_object_or_404
class RunValuesDetailAPIView(RetrieveAPIView):
queryset = RunValue.objects.all()
serializer_class = RunValuesDetailSerializer
permission_classes = [IsOwnerOrReadOnly]]
lookup_fields = ["run_id", "run_parameter_id"]
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
filter = {}
for field in self.lookup_fields:
if self.kwargs[field]: # Ignore empty fields.
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
# url
url(r'^run-values/(?P<run_id>\d+)/(?P<run_parameter_id>\d+)/$', RunValuesDetailAPIView.as_view(), name='values_list_detail'),
但是你需要注意的一件大事是不要有相同的run_id
和run_parameter_id
的重复条目,那么它会抛出错误。 为避免这种情况,请使用unique_together=['run', 'run_parameter']
或者您可以在视图中使用queryset.filter(**filter).first()
而不是get_object_or_404
。 但是当创建重复条目时,第二个选项会产生错误的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.