Преобразование POST в PUT с помощью Tastypie

Полное раскрытие информации: перекрестная публикация в Tastypie Google Group

У меня есть ситуация, когда у меня ограниченный контроль над тем, что отправляется на мой API. По сути, есть два веб-сервиса, от которых мне нужно иметь возможность принимать данные POST. Оба используют простые действия POST с данными, закодированными в urlencode (по сути, базовая отправка формы).

Думая об этом с точки зрения «завитка», это похоже на:

curl --data "id=1&foo=2" http://path/to/api

Моя проблема в том, что я не могу обновлять записи с помощью POST. Поэтому мне нужно настроить ресурс модели (я полагаю), чтобы, если указан идентификатор, POST действовал как PUT вместо POST.

API.py

class urlencodeSerializer(Serializer):
    formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist', 'urlencoded']
    content_types = {
        'json': 'application/json',
        'jsonp': 'text/javascript',
        'xml': 'application/xml',
        'yaml': 'text/yaml',
        'html': 'text/html',
        'plist': 'application/x-plist',
        'urlencoded': 'application/x-www-form-urlencoded',
        }
    # cheating
    def to_urlencoded(self,content): 
        pass
    # this comes from an old patch on github, it was never implemented
    def from_urlencoded(self, data,options=None):
        """ handles basic formencoded url posts """
        qs = dict((k, v if len(v)>1 else v[0] )
            for k, v in urlparse.parse_qs(data).iteritems())
        return qs


class FooResource(ModelResource):
    class Meta:
        queryset = Foo.objects.all() # "id" = models.AutoField(primary_key=True)
        resource_name = 'foo'
        authorization = Authorization() # only temporary, I know.
        serializer = urlencodeSerializer()

urls.py

foo_resource = FooResource

...
url(r'^api/',include(foo_resource.urls)),
) 

В #tastypie на Freenode Ghost[] предложил мне перезаписать post_list(), создав такую ​​функцию в ресурсе модели, однако мне пока не удалось это использовать.

def post_list(self, request, **kwargs):
    if request.POST.get('id'): 
        return self.put_detail(request,**kwargs) 
    else: 
        return super(YourResource, self).post_list(request,**kwargs)

К сожалению, этот метод не работает для меня. Я надеюсь, что более широкое сообщество может предоставить некоторые рекомендации или решение этой проблемы.

Примечание. Я не могу перезаписать заголовки, полученные от клиента (согласно: http://django-tastypie.readthedocs.org/en/latest/resources.html#using-put-delete-patch-in-unsupported-places)


person Brandon Bertelsen    schedule 27.02.2013    source источник
comment
Я использую метод obj_create, как эта ссылка использовать вновь созданный объект"> stackoverflow.com/questions/10070173/ и отлично работает   -  person Luis Alfredo    schedule 22.04.2014


Ответы (2)


У меня была аналогичная проблема при создании пользователя, когда я не мог проверить, существует ли уже запись. В итоге я создал собственный метод проверки, который проверял, не существует ли пользователь, и в этом случае сообщение будет работать нормально. Если пользователь существовал, я обновил запись из метода проверки. API по-прежнему возвращает ответ 400, но запись обновляется. Это кажется немного хакерским, но...

person Cathal    schedule 28.02.2013

По рекомендации Катала я смог использовать функцию проверки для обновления необходимых мне записей. Хотя это не возвращает правильный код... он работает.

from tastypie.validation import Validation
import string # wrapping in int() doesn't work

class Validator(Validation): 
    def __init__(self,**kwargs):
        pass

    def is_valid(self,bundle,request=None):
        if string.atoi(bundle.data['id']) in Foo.objects.values_list('id',flat=True):
                # ... update code here
        else:
            return {}

Убедитесь, что вы указали validation = Validator() в метаданных ModelResource.

person Brandon Bertelsen    schedule 01.03.2013
comment
Да, он не возвращает правильный код. Удалось ли вам найти решение для него? - person itsji10dra; 29.09.2017
comment
Он возвращает отказ, но на самом деле не терпит неудачу. Это было моим решением. - person Brandon Bertelsen; 30.09.2017