Я получаю ошибку 400 Bad Request при использовании django-piston

Я пытаюсь использовать Piston для поддержки REST для Django. Я выполнил свои обработчики в соответствии с предоставленной документацией. Проблема в том, что я могу "читать" и "удалять" свой ресурс, но я не могу "создать" или "обновить". Каждый раз, когда я нажимаю соответствующий api, я получаю ошибку 400 Bad request.

Я расширил класс Resource для 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

Пожалуйста, дайте мне знать, как я могу заставить метод create работать с помощью операции POST?

Ответ 1

Это происходит потому, что 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',
)

Ответ 2

Предлагаемые решения все еще не работали для меня (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',
)

Я не заметил никакого побочного эффекта, но я не могу обещать ему пуленепробиваемый.

Ответ 3

Я объединил некоторые из других людей и добавил поддержку любого типа контента, например 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

Ответ 4

Я думал, что решение 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

Ответ 5

В 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

Ответ 6

Это решение, которое сработало для меня после настройки:

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

Ответ 7

У нас был ресурс, который просто обновлял временную метку на основе учетных данных запроса и PUT. Оказывается, что Piston не любит PUT без полезной нагрузки. Добавление пустой полезной нагрузки строки '' исправило ее.

Быстрый поиск в Google показывает, что другие системы, такие как Apache, могут не нравиться PUT без полезной нагрузки.