Как различать по методу HTTP в django urlpatterns

У меня возникают трудности с поиском информации об этом, возможно, это не правильный подход. Я хотел бы направить запрос на две разные функции просмотра на основе метода http (GET или POST или DELETE или PUT).

Как это обычно делается в REST apis, это будет означать, что тот же URL имеет другое значение, основанное на методе HTTP.

Я не вижу способа сделать это в файле urls.py django, мне бы хотелось что-то вроде:

url(r'^tasks$', 'app.views.get_tasks', method='get'),
url(r'^tasks$', 'app.views.create_task',  method='post'),

(примечание: я работаю с django 1.4)

Ответ 1

Я не думаю, что вы можете сделать это с помощью разных функций, не добавляя в URL-адрес пустую логику (что никогда не бывает хорошей идеей), но вы можете проверить внутри функции для метода запроса:

def myview(request):
    if request.method == 'GET':
        # Code for GET requests
    elif request.method == 'POST':
        # Code for POST requests

Вы также можете переключиться на представления на основе классов. Затем вам нужно будет определить метод для каждого из HTTP-методов:

class CreateMyModelView(CreateView):
    def get(self, request, *args, **kwargs):
        # Code for GET requests

    def post(self, request, *args, **kwargs):
        # Code for POST requests

Если вы решите пойти на основе класса, другой хороший ресурс http://ccbv.co.uk/.

Ответ 2

Поскольку Django позволяет использовать вызовы в конфигурации url, вы можете сделать это с помощью вспомогательной функции.

def method_dispatch(**table):
    def invalid_method(request, *args, **kwargs):
        logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
            extra={
                'status_code': 405,
                'request': request
            }
        )
        return HttpResponseNotAllowed(table.keys())

    def d(request, *args, **kwargs):
        handler = table.get(request.method, invalid_method)
        return handler(request, *args, **kwargs)
    return d

Чтобы использовать его:

url(r'^foo',
    method_dispatch(POST = post_handler,
                    GET = get_handler)),