使用 django-piston 时出现 400 Bad Request 错误

发布于 2024-10-09 14:29:28 字数 1068 浏览 5 评论 0原文

我正在尝试使用 Piston 为 Django 提供 REST 支持。 我已经按照提供的文档实现了我的处理程序。 问题是我可以“读取”和“删除”我的资源,但无法“创建”或“更新”。 每次我点击相关 api 时,都会收到 400 Bad request 错误。

我通过使用以下常用代码片段扩展了 csrf 的资源类:

class CsrfExemptResource(Resource):
    """A Custom Resource that is csrf exempt"""
    def __init__(self, handler, authentication=None):
        super(CsrfExemptResource, self).__init__(handler, authentication)
        self.csrf_exempt = getattr(self.handler, 'csrf_exempt', True)

我的类(代码片段)如下所示:

user_resource = CsrfExemptResource(User)

class User(BaseHandler):
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')

    @require_extended
    def create(self, request):
        email = request.GET['email']
        password = request.GET['password']
        phoneNumber = request.GET['phoneNumber']
        firstName = request.GET['firstName']
        lastName = request.GET['lastName']
        self.createNewUser(self, email,password,phoneNumber,firstName,lastName)
        return rc.CREATED

请让我知道如何使用 POST 操作让 create 方法工作?

I am trying to use Piston to provide REST support to Django.
I have implemented my handlers as per the documentation provided .
The problem is that i can "read" and "delete" my resource but i cannot "create" or "update".
Each time i hit the relevant api i get a 400 Bad request Error.

I have extended the Resource class for csrf by using this commonly available code snippet:

class CsrfExemptResource(Resource):
    """A Custom Resource that is csrf exempt"""
    def __init__(self, handler, authentication=None):
        super(CsrfExemptResource, self).__init__(handler, authentication)
        self.csrf_exempt = getattr(self.handler, 'csrf_exempt', True)

My class (code snippet) looks like this:

user_resource = CsrfExemptResource(User)

class User(BaseHandler):
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')

    @require_extended
    def create(self, request):
        email = request.GET['email']
        password = request.GET['password']
        phoneNumber = request.GET['phoneNumber']
        firstName = request.GET['firstName']
        lastName = request.GET['lastName']
        self.createNewUser(self, email,password,phoneNumber,firstName,lastName)
        return rc.CREATED

Please let me know how can i get the create method to work using the POST operation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

萌辣 2024-10-16 14:29:28

发生这种情况是因为 Piston 不喜欢 ExtJS 将“charset=UTF-8”放入标头的内容类型中。

通过添加一些中间件使内容类型对 Piston 更友好,可以轻松修复,在应用程序基目录中创建一个名为 middleware.py 的文件:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if request.META['CONTENT_TYPE'] == 'application/x-www-form-urlencoded; charset=UTF-8':
            request.META['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
        return None

然后只需将此中间件包含在 settings.py 中:

MIDDLEWARE_CLASSES = (
    'appname.middleware.ContentTypeMiddleware',
)

This is happening because Piston doesn't like the fact that ExtJS is putting "charset=UTF-8" in the content-type of the header.

Easily fixed by adding some middleware to make the content-type a bit more Piston friendly, create a file called middleware.py in your application base directory:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if request.META['CONTENT_TYPE'] == 'application/x-www-form-urlencoded; charset=UTF-8':
            request.META['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
        return None

Then simply include this middleware in your settings.py:

MIDDLEWARE_CLASSES = (
    'appname.middleware.ContentTypeMiddleware',
)
剪不断理还乱 2024-10-16 14:29:28

建议的解决方案仍然对我不起作用(django 1.2.3/piston 0.2.2),所以我调整了 joekrell 解决方案,这最终起作用了(我只使用 POST 和 PUT,但大概你可以将其他动词添加到列表中):

class ContentTypeMiddleware(object):

def process_request(self, request):

    if request.method in ('POST', 'PUT'):
        # dont break the multi-part headers !
        if not 'boundary=' in request.META['CONTENT_TYPE']:
            del request.META['CONTENT_TYPE']

with:

MIDDLEWARE_CLASSES = (
'appname.middleware.ContentTypeMiddleware',
)

我没有注意到任何副作用,但我不能保证它是防弹的。

Proposed solutions still did not work for me (django 1.2.3/piston 0.2.2) so I've tweaked joekrell solution and this finally works (I'm only using POST and PUT, but presumably you can add other verbs to the list):

class ContentTypeMiddleware(object):

def process_request(self, request):

    if request.method in ('POST', 'PUT'):
        # dont break the multi-part headers !
        if not 'boundary=' in request.META['CONTENT_TYPE']:
            del request.META['CONTENT_TYPE']

with:

MIDDLEWARE_CLASSES = (
'appname.middleware.ContentTypeMiddleware',
)

I haven't noticed any side-effect, but I can't promise it's bullet-proof.

微凉徒眸意 2024-10-16 14:29:28

我结合了其他人所说的一些内容,并添加了对任何内容类型的支持,例如 json...

class ContentTypeMiddleware(object):
    def process_request(self, request):
        if request.method in ('POST', 'PUT') and request.META['CONTENT_TYPE'].count(";") > 0:
            request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0]
        return None

I have combined some of what other people have said, and added support for any content type, json for instance...

class ContentTypeMiddleware(object):
    def process_request(self, request):
        if request.method in ('POST', 'PUT') and request.META['CONTENT_TYPE'].count(";") > 0:
            request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0]
        return None
所有深爱都是秘密 2024-10-16 14:29:28

我认为埃里克的解决方案效果最好,但在管理中保存内容时遇到了问题。如果其他人遇到这个问题,这个调整似乎可以解决这个问题:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if request.method in ('POST') and not 'boundary=' in request.META['CONTENT_TYPE']:
            request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0]
        return None

I thought Eric's solution worked the best but then ran into problems when saving things in admin. This tweak seems to fix it if anyone else comes across it:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if request.method in ('POST') and not 'boundary=' in request.META['CONTENT_TYPE']:
            request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0]
        return None
零崎曲识 2024-10-16 14:29:28

在 utils.py 中,更改此项。

def content_type(self):
    """
    Returns the content type of the request in all cases where it is
    different than a submitted form - application/x-www-form-urlencoded
    """
    type_formencoded = "application/x-www-form-urlencoded"

    ctype = self.request.META.get('CONTENT_TYPE', type_formencoded)

    if ctype.strip().lower().find(type_formencoded) >= 0:
        return None

    return ctype

https://bitbucket.org/jespern /django-piston/issue/87/split-charset-encoding-form-content-type

In utils.py, change this.

def content_type(self):
    """
    Returns the content type of the request in all cases where it is
    different than a submitted form - application/x-www-form-urlencoded
    """
    type_formencoded = "application/x-www-form-urlencoded"

    ctype = self.request.META.get('CONTENT_TYPE', type_formencoded)

    if ctype.strip().lower().find(type_formencoded) >= 0:
        return None

    return ctype

https://bitbucket.org/jespern/django-piston/issue/87/split-charset-encoding-form-content-type

游魂 2024-10-16 14:29:28

经过调整后,这是对我有用的解决方案:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if 'charset=UTF-8' in request.META['CONTENT_TYPE']:
            request.META['CONTENT_TYPE'] = request.META['CONTENT_TYPE'].replace('; charset=UTF-8','')
        return None

This is solution which worked for me, after a tweak:

class ContentTypeMiddleware(object):

    def process_request(self, request):
        if 'charset=UTF-8' in request.META['CONTENT_TYPE']:
            request.META['CONTENT_TYPE'] = request.META['CONTENT_TYPE'].replace('; charset=UTF-8','')
        return None
柳絮泡泡 2024-10-16 14:29:28

我们有一个资源,它只是根据请求凭据和 PUT 更新时间戳。事实证明,Piston 不喜欢没有有效负载的 PUT。添加一个空字符串有效负载 '' 修复了它。

快速 Google 搜索表明 Apache 等其他系统可能也不喜欢没有有效负载的 PUT。

We had a resource that was simply updating a timestamp based on the request credentials and PUT. It turns out that Piston does not like PUT without a payload. Adding an empty string payload '' fixed it.

A quick Google search indicates that other systems like Apache may not like PUT without a payload, as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文