我正在编写一个插件包装器来提供app到restfull,问题是应用程序不处理PUT请求,然后我从resfull得到一个PUT请求并且应该更改请求的方法进入POST请求。
我试过这个:
self.context['request'].method = 'POST'
但显然不起作用
我怎么能这样做? 感谢
串行器代码:
class PageEditSerializer(serializers.ModelSerializer):
"""
Serializer Class to edit and delete a Page.
"""
raw = serializers.CharField()
def save(self):
#no works
self.context['request'].method = 'POST'
"""call to waliki new function"""
views.edit(self.context['request'], self.instance.slug)
class Meta():
model = Page
fields = ('id', 'title', 'slug', 'raw', )
read_only_fields = ('id', 'slug', )
查看代码:
class PageEditView(generics.RetrieveUpdateAPIView):
"""
A simple View to edit a Page.
"""
lookup_field = 'slug'
serializer_class = PageEditSerializer
permission_classes = (permissions.AllowAny, )
def get_queryset(self):
return Page.objects.filter(slug=self.kwargs['slug'])
答案 0 :(得分:5)
我将把答案分为三部分。
PART-1:Django Rest Framework(DRF)是否明确支持请求方法覆盖?
是的,DRF提供了两种可以覆盖请求方法的方法。
DRF通过使用隐藏表单字段重载PUT
请求,支持基于浏览器的DELETE
,POST
和其他方法。
例如:
<form action="/some/url" method="POST">
<input type="hidden" name="_method" value="PUT">
</form>
在上面的示例中,我们使用名为POST
的隐藏表单字段将PUT
方法与_method
重叠。
request.method
现在将返回PUT
而不是POST
。
DRF还支持通过X-HTTP-Method-Override
标头覆盖方法。只需使用所需方法的值设置X-HTTP-Method-Override
标题即可。
例如,在jQuery中通过PATCH
发出POST
请求:
$.ajax({
url: '/myresource/',
method: 'POST',
headers: {'X-HTTP-Method-Override': 'PATCH'},
...
});
此方法在处理非形式内容(如JSON)或处理较旧的Web服务器和/或无法识别特定HTTP方法(如PATCH
的托管服务提供商)时非常有用。
第2部分:为什么您的代码无效?
请求方法存储在变量_method
中,属性method
用于访问它的值。
如果为请求的setter
属性定义了_method
,那么设置请求方法值的方法就会奏效。由于未定义,因此您无法以您的方式设置请求method
的值。
PART-3:如何覆盖您案例中的请求方法?
解决方案-1(快速):直接设置_method
属性
您可以直接将_method
设置为所需的值,该值将覆盖请求方法。
class PageEditSerializer(serializers.ModelSerializer):
"""
Serializer Class to edit and delete a Page.
"""
raw = serializers.CharField()
def save(self):
self.context['request']._method = 'POST' # override the request method
"""call to waliki new function"""
views.edit(self.context['request'], self.instance.slug)
class Meta():
model = Page
fields = ('id', 'title', 'slug', 'raw', )
read_only_fields = ('id', 'slug', )
这会将请求方法覆盖为POST
。
解决方案-2:通过中间件在请求中设置X-HTTP-Method-Override
标头
在DRF视图中调用initialize_request()
时,DRF会检查Django请求中的X-HTTP-Method-Override
标头。如果已设置,它将覆盖当前请求method
到该标头中定义的方法。
因此,在DRF初始化并准备DRF request
之前,我们可以将X-HTTP-Method-Override
标头设置为我们所需的方法,该方法将覆盖请求方法。
我们创建了一个PutRequestMethodOverrideMiddleware
类,并在请求为X-HTTP-Method-Override
并且尚未设置此特定标头的情况下在请求中设置PUT
标头。
class PutRequestMethodOverrideMiddleware(object):
def process_request(self, request):
override_method = request.META.get('X-HTTP-Method-Override')
if request.method=='PUT' and not override_method:
# Override method in case of PUT requests and header not already set
request.META['X-HTTP-Method-Override'] = 'POST' # set to desired method value
return
然后在您的设置中,将此中间件添加到MIDDLEWARE_CLASSES
。
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
...
...
# your custom middleware
'my_project.middlewares.PutRequestMethodOverrideMiddleware',
)
但请记住,此方法会将所有PUT
请求方法覆盖为POST
方法。
此处,PutRequestMethodOverrideMiddleware
将在最后执行。您可以将它放在您希望它执行的位置。