gpt4 book ai didi

django - 如何访问 Tastypie 自定义身份验证中的 POST 数据

转载 作者:行者123 更新时间:2023-12-04 02:02:55 25 4
gpt4 key购买 nike

我正在尝试在 Tastypie 中编写自定义身份验证。基本上,我想使用 post 参数进行身份验证,我根本不想使用 django 身份验证,所以我的代码看起来像:

class MyAuthentication(Authentication):
def is_authenticated(self, request, **kwargs):
if request.method == 'POST':
token = request.POST['token']
key = request.POST['key']
return is_key_valid(token,key)

这或多或少是一个想法。问题是我不断收到以下错误:
"error_message": "You cannot access body after reading from request's data stream"

我知道这与我正在访问 POST 的事实有关,但我不知道是否有办法解决它。有任何想法吗?
谢谢。

编辑:也许我忘了提到最重要的事情。我正在使用在 github 中找到的技巧处理表单数据。我的资源来自多部分资源
class MultipartResource(object):
def deserialize(self, request, data, format=None):
if not format:
format = request.META.get('CONTENT_TYPE', 'application/json')

if format == 'application/x-www-form-urlencoded':
return request.POST

if format.startswith('multipart'):
data = request.POST.copy()
data.update(request.FILES)
return data
return super(MultipartResource, self).deserialize(request, data, format)

最佳答案

问题是 Content-Type在您的请求标题中未正确设置。 [ Reference ]

Tastypie 只识别 xml , json , yamlbplist .所以在发送POST请求时,需要设置Content-Type在其中任何一个的请求 header 中(例如,application/json)。

编辑 :

似乎您正在尝试通过以下方式发送包含文件的多部分表单
好吃。

Issac Kelly 关于 Tastypie 文件上传支持的一点背景知识
路线图 1.0 最终版(尚未发布):

  1. Implement a Base64FileField which accepts base64 encoded files (like the one in issue #42) for PUT/POST, and provides the URL for GET requests. This will be part of the main tastypie repo.
  2. We'd like to encourage other implementations to implement as independent projects. There's several ways to do this, and most of them are slightly finicky, and they all have different drawbacks, We'd like to have other options, and document the pros and cons of each


这意味着至少目前,Tastypie 不正式支持多部分
上传文件。然而,据说在野外有 fork 可以工作
好吧, this是其中之一
他们。不过我还没有测试过。

现在让我尝试解释您遇到该错误的原因。

在美味 resource.py , line 452 :
def dispatch(self, request_type, request, **kwargs):
"""
Handles the common operations (allowed HTTP method, authentication,
throttling, method lookup) surrounding most CRUD interactions.
"""
allowed_methods = getattr(self._meta, "%s_allowed_methods" % request_type, None)

if 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
request.method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE']

request_method = self.method_check(request, allowed=allowed_methods)
method = getattr(self, "%s_%s" % (request_method, request_type), None)

if method is None:
raise ImmediateHttpResponse(response=http.HttpNotImplemented())

self.is_authenticated(request)
self.is_authorized(request)
self.throttle_check(request)

# All clear. Process the request.
request = convert_post_to_put(request)
response = method(request, **kwargs)

# Add the throttled request.
self.log_throttled_access(request)

# If what comes back isn't a ``HttpResponse``, assume that the
# request was accepted and that some action occurred. This also
# prevents Django from freaking out.
if not isinstance(response, HttpResponse):
return http.HttpNoContent()

return response
convert_post_to_put(request)从这里调用。和 here is the code for convert_post_to_put :
# Based off of ``piston.utils.coerce_put_post``. Similarly BSD-licensed.
# And no, the irony is not lost on me.
def convert_post_to_VERB(request, verb):
"""
Force Django to process the VERB.
"""
if request.method == verb:
if hasattr(request, '_post'):
del(request._post)
del(request._files)

try:
request.method = "POST"
request._load_post_and_files()
request.method = verb
except AttributeError:
request.META['REQUEST_METHOD'] = 'POST'
request._load_post_and_files()
request.META['REQUEST_METHOD'] = verb
setattr(request, verb, request.POST)

return request


def convert_post_to_put(request):
return convert_post_to_VERB(request, verb='PUT')

而且这种方法并不是真的打算像它那样处理多部分
阻止对 request.body 的任何进一步访问的副作用因为 _load_post_and_files()方法将设置 _read_started标记为 True :

Django request.body _load_post_and_files() :
@property
def body(self):
if not hasattr(self, '_body'):
if self._read_started:
raise Exception("You cannot access body after reading from request's data stream")
try:
self._body = self.read()
except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])
self._stream = BytesIO(self._body)
return self._body

def read(self, *args, **kwargs):
self._read_started = True
return self._stream.read(*args, **kwargs)

def _load_post_and_files(self):
# Populates self._post and self._files
if self.method != 'POST':
self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
return
if self._read_started and not hasattr(self, '_body'):
self._mark_post_parse_error()
return

if self.META.get('CONTENT_TYPE', '').startswith('multipart'):
if hasattr(self, '_body'):
# Use already read data
data = BytesIO(self._body)
else:
data = self
try:
self._post, self._files = self.parse_file_upload(self.META, data)
except:
# An error occured while parsing POST data. Since when
# formatting the error the request handler might access
# self.POST, set self._post and self._file to prevent
# attempts to parse POST data again.
# Mark that an error occured. This allows self.__repr__ to
# be explicit about it instead of simply representing an
# empty POST
self._mark_post_parse_error()
raise
else:
self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()

所以,你可以(虽然可能不应该)猴子补丁 Tastypie's convert_post_to_VERB()方法通过设置 request._body通过调用 request.body然后立即设置 _read_started=False以便 _load_post_and_files()将从 _body 读取并且不会设置 _read_started=True :
def convert_post_to_VERB(request, verb):
"""
Force Django to process the VERB.
"""
if request.method == verb:
if hasattr(request, '_post'):
del(request._post)
del(request._files)

request.body # now request._body is set
request._read_started = False # so it won't cause side effects

try:
request.method = "POST"
request._load_post_and_files()
request.method = verb
except AttributeError:
request.META['REQUEST_METHOD'] = 'POST'
request._load_post_and_files()
request.META['REQUEST_METHOD'] = verb
setattr(request, verb, request.POST)

return request

关于django - 如何访问 Tastypie 自定义身份验证中的 POST 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12522332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com