我有模型运行。它代表数据的时间段测量:
class Run(models.Model):
start_time = models.DateTimeField(db_index=True)
end_time = models.DateTimeField()
chamber = models.ForeignKey(Chamber, on_delete=models.CASCADE)
class Meta:
unique_together=(('start_time', 'chamber'),)
以下是此端点的POST请求数据模糊示例:
{
"start_time": "2018-11-11T12:00:00Z",
"end_time": "2018-11-11T12:00:01Z",
"chamber": "My Test Chamber"
}
运行属于商会,并且 start_time 和 end_time
运行无法共享相同的商会和 start_time 。如果我在请求数据模糊中获得相同的 start_time 和商会,则表示运行仍在进行中,需要进行更新。
当请求第一次出现时,我创建了一个运行对象,该工作正常。发送请求的传感器将发送相同的POST请求数据模糊,只更改数据模糊的 end_time ,只要“运行”正在进行即可。
传感器不发送PUT或PATCH,它只发送POST,这可能是一个问题,但它是不可修复的,所以我必须处理POST请求。
我想要的行为是:
这是Serializer:
class RunsCreateSerializer(ModelSerializer):
class Meta:
model = Run
fields = [
'id',
'chamber',
'start_time',
'end_time'
]
这是API端点上的views.py:
class RunsCreateAPIView(CreateAPIView):
queryset = Run.objects.all()
queryset = queryset.prefetch_related('chamber')
serializer_class = RunsCreateSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs):
try:
chamber = Chamber.objects.get(chamber_name=request.data["chamber"])
request.data["chamber"] = chamber.id
except:
print("Invalid chamber name")
serializer = RunsCreateSerializer(data=request.data)
print(serializer)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors)
现在,我发现我必须稍微修改views.py上的“创建”,因为传感器将 Chamber 作为字符串标识符发送。然后,我必须检查该 Chamber 表中的字符串并检索对象实例,然后修改请求数据,将 Chamber 字符串替换为我的数据库中的ID。我不确定这是否是正确的方法,但它对我有用。
现在我试图解决这个问题:
在serializers.py上:
def create(self, validated_data):
run, created = Run.objects.update_or_create(
chamber=validated_data.get('chamber'),
start_time=validated_data.get('start_time'),
end_time=validated_data.get('end_time'))
return run
def update(self, run, validated_data):
run.chamber = validated_data.get('chamber', run.chamber)
run.start_time = validated_data.get('start_time', run.start_time)
run.created = validated_data.get('created', run.created)
run.save()
return run
我想通过在我的序列化程序上执行此操作,我可以更新对象,但它似乎没有达到这一点(在创建和更新方法上尝试使用print(“完整性检查”),I看不到我的理智检查输出,所以我知道我没有达到这一点。)
我怀疑它与我重写视图上的create方法,但我不确定。
如果您知道如何更新对象,并且可能让序列化程序/视图处理 Chamber 名称的字符串,而不必插入替换ID字符串的方法,我将非常感谢您帮助
答案 0 :(得分:1)
正如您提到的那样,您将chamber
作为字符串,因此要正确处理该关系,请在序列化程序中使用chamber = serializer.StringRelatedField()
。删除在序列化器/视图中覆盖的所有方法。只需在您的RunsCreateAPIView
中添加以下内容即可。
def perform_create(self, serializer):
chamber=serializer.validated_data.get('chamber'),
start_time=serializer.validated_data.get('start_time')
end_time=serializer.validated_data.get('end_time')
Run.objects.update_or_create(
chamber=chamber,
start_time=start_time,
defaults = {"end_time": end_time}
)
update_or_create
将根据chamber和start_time的值自动处理创建或更新。
答案 1 :(得分:0)
我们可以简单地覆盖方法def perform_create(self, serializer):
class RunsCreateAPIView(CreateAPIView):
# some code
def perform_create(self, serializer):
chamber=serializer.validated_data.get('chamber'),
chamber = Chamber.objects.get(chamber_name=chamber)
start_time=serializer.validated_data.get('start_time')
end_time=serializer.validated_data.get('end_time'),
obj_lst = Run.objects.filter(chamber=chamber, start_time=start_time)
if obj_lst:
obj_lst.update(
chamber=chamber,
start_time=start_time,
end_time=end_time)
else:
Run.objects.create(chamber=chamber,
start_time=start_time,
end_time=end_time)