【发布时间】:2020-10-02 02:20:27
【问题描述】:
上下文
对于特定用例,我需要能够使用 GET 请求而不是 PATCH 请求来更新我的 Visitor 模型的单个字段。
我的相关访问者模型如下所示:
# models.py
class Visitor(models.Model):
visitor_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
customers = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_visitors')
audiences = models.ManyToManyField(Audience, related_name='audience_visitors')
cid = models.CharField(max_length=255, unique=True)
uid = models.CharField(max_length=255)
cup = JSONField(null=True)
def __str__(self):
return self.cid
class Meta:
db_table = 'visitor'
我正在使用这样一个简单的序列化程序:
# serializers.py
class VisitorSerializer(serializers.ModelSerializer):
class Meta:
model = Visitor
fields = ('customers', 'cid', 'uid', 'cup')
我可以只更新特定 Visitor 的 cup 字段,该字段使用具有如下 PATCH 的唯一 cid 字段进行查找:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.serializer_class(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
问题
问题是我无法使用 GET 请求根据给定的唯一 cid 字段更新访客的 cup 字段。
我尝试了什么
正如this answer by Uri Shalit 建议的那样,我尝试在VisitorViewSet 中覆盖get_serializer(),并尝试在list() 中使用它,如下所示:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def get_serializer(self, *args, **kwargs):
kwargs['partial'] = True
return super(VisitorViewSet, self).get_serializer(*args, **kwargs)
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
但是,基于 cid 字段仅更新特定访客的 cup 字段适用于 PATCH 请求,但不会使用 GET 请求更新所述字段。也没有错误。
预期行为
发出一个 GET 请求,其中包含 cid 以识别访客,cup 包含需要为给定访客更新的数据。我知道它违反了 REST 原则,但对于这个用例,我需要使用 GET 请求而不是 PATCH 请求来进行部分更新。
任何正确方向的帮助或指示将不胜感激!
【问题讨论】:
-
我认为你不应该使用 GET 请求来更新,因为 GET 请求可以被多次调用(例如大多数在线爬虫使用带有所有 url 名称的 GET 请求进行爬虫)。我认为您应该在参数
/data/1中有一个带有 id 的 PUT 请求,并在正文中传递更新字段 -
这个用例要求它是一个 GET 请求。我可以使用 PUT 或 PATCH 请求来实现我想要的,但它必须是 GET 请求,因为它用于跟踪。
-
您要更新单个访问者实例还是实例列表?您要用于更新的数据是来自前端还是后端?如果它来自前面,那么您只能将其作为 url 参数传递,因为 GET 请求没有正文。必须回答这些问题才能为您提供帮助
-
我想更新单个访问者实例。数据作为 GET 请求来自前端,数据作为 URL 参数传递
标签: python django django-rest-framework