【问题标题】:I get a 400 Bad Request error while using django-piston使用 django-piston 时出现 400 Bad Request 错误
【发布时间】:2011-05-31 01:18:29
【问题描述】:

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

我使用这个常用的代码 sn-p 扩展了 csrf 的 Resource 类:

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)

我的班级(代码 sn-p)如下所示:

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 方法工作?

【问题讨论】:

  • 好的,我从设置文件中注释掉了“django.middleware.csrf.CsrfViewMiddleware”,而不是使用资源类的扩展名。我仍然看到这个问题
  • 您如何尝试与“create”或“update”对应的“PUT”或“POST”HTTP 操作?你怎么知道这个客户端代码正在创建一个正确有效的 HTTP 请求?
  • 对于 POST,我使用了一个 restclient WizTools.org,我可以从中显式创建一个 POST 请求。所以至少我确信请求通过了,我猜这已经足够了。

标签: python django json rest django-piston


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

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

      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
      

      【讨论】:

        【解决方案4】:

        我结合了其他人所说的一些内容,并添加了对任何内容类型的支持,例如 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
        

        【讨论】:

        • 这是最好的解决方案。谢谢。
        • 将它用于 POST 会破坏其他东西,但它解决了我仅用于 PUT 时的问题
        【解决方案5】:

        提出的解决方案对我仍然不起作用(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']
        

        与:

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

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

        【讨论】:

        • 是的,您的解决方案也适用于我(Django 1.3,Piston 0.2.2)。总的来说,活塞看起来像是一个废弃的东西——它已经很长时间没有更新了。
        【解决方案6】:

        发生这种情况是因为 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',
        )
        

        【讨论】:

          【解决方案7】:

          在 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

          【讨论】:

            猜你喜欢
            • 2014-03-20
            • 2015-11-16
            • 1970-01-01
            • 2023-01-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-29
            • 2014-08-22
            相关资源
            最近更新 更多