Django: создание / изменение объекта запроса - PullRequest
4 голосов
/ 22 ноября 2010

Я пытаюсь создать приложение URL-псевдонима, которое позволяет пользователю создавать псевдонимы для существующего URL на своем веб-сайте.

Я пытаюсь сделать это через промежуточное ПО, где отмечен request.META['PATH_INFO']для записей базы данных псевдонимов:

try:
    src: request.META['PATH_INFO']
    alias = Alias.objects.get(src=src)
    view = get_view_for_this_path(request)

    return view(request) 
except Alias.DoesNotExist:
   pass

return None

Однако для правильной работы очень важно, чтобы (как минимум) PATH_INFO был изменен на путь назначения.

Теперь естьнекоторые фрагменты, которые позволяют разработчику создавать объекты запросов на тестирование (http://djangosnippets.org/snippets/963/, http://djangosnippets.org/snippets/2231/),, но в них говорится, что они предназначены для целей тестирования.

Конечно, это может бытьфрагменты подходят для использования в реальной среде, но мои знания об обработке запросов в Django слишком слабы, чтобы оценить это.

Ответы [ 3 ]

4 голосов
/ 22 ноября 2010

Вместо того подхода, который вы используете, рассматривали ли вы приложение Redirects ?

Он не будет невидимым псевдонимом пути / foo /, чтобы вернуть панель просмотра (), но перенаправит / foo / на / bar /

2 голосов
/ 24 ноября 2010

(опубликовано как ответ, потому что комментарии, кажется, не поддерживают разрывы строк или другую разметку)

Спасибо за совет, у меня такое же чувство в отношении изменения атрибутов запроса. Должна быть причина, по которой в руководстве по Django указано, что их следует рассматривать только для чтения.

Я придумал это промежуточное ПО:

def process_request(self, request):
    try:
        obj = A.objects.get(src=request.path_info.rstrip('/')) #The alias record.
        view, args, kwargs = resolve_to_func(obj.dst + '/') #Modified http://djangosnippets.org/snippets/2262/
        request.path = request.path.replace(request.path_info, obj.dst)
        request.path_info = obj.dst
        request.META['PATH_INFO'] = obj.dst
        request.META['ROUTED_FROM'] = obj.src
        request.is_routed = True

        return view(request, *args, **kwargs)
    except A.DoesNotExist: #No alias for this path
        request.is_routed = False
    except TypeError: #View does not exist.
        pass

    return None

Но, учитывая возражения против изменения атрибутов запросов, не будет ли лучшим решением просто пропустить эту часть и добавить только части is_routed и ROUTED_TO (вместо перенаправленных из)?

Код, основанный на исходном пути, может затем использовать этот ключ из META.

Выполнение этого с помощью URLConfs невозможно, поскольку этот псевдоним предназначен для того, чтобы конечный пользователь мог настроить свои собственные URL-адреса, предполагая, что конечный пользователь не имеет доступа к базе кода или не знает, как написать свой собственный URLConf.

Хотя можно было бы написать функцию, которая преобразует файл, читаемый пользователем и редактируемый (например, XML), в действительные URL-адреса Django, создается впечатление, что использование записей в базе данных позволяет более динамически генерировать псевдонимы (другие объекты определяют свои собственные). псевдонимы).

1 голос
/ 13 ноября 2012

Извините за некропост, но я только нашел эту ветку при поиске ответов.Мое решение кажется проще.Может быть, а) я зависел от новых функций django или б) мне не хватает ловушки.

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

1.2.3.4 - - [12/Nov/2012:21:23:11 -0800] "GET /article/my-slug-name%3Fpage%3D2 HTTP/1.1" 1209 404 "-" "Mediapartners-Google

Обычно я просто игнорирую сломанныйбот, но этот я хочу умиротворить, потому что он должен лучше ориентироваться на наши объявления (это бот Google AdSense), что приводит к повышению дохода - если он может видеть наш контент.Ходят слухи, что он не следует за перенаправлениями, поэтому я хотел найти решение, похожее на исходный Q. Я не хочу, чтобы обычные клиенты обращались к страницам по этим неработающим URL-адресам, поэтому я обнаружил пользовательский агент.Другие приложения, вероятно, не будут этого делать.

Я согласен, что перенаправление обычно будет правильным ответом.

Мое (полное?) Решение:

from django.http import QueryDict
from django.core.urlresolvers import NoReverseMatch, resolve

class MediapartnersPatch(object):
    def process_request(self, request):
        # short-circuit asap
        if request.META['HTTP_USER_AGENT'] != 'Mediapartners-Google':
            return None

        idx = request.path.find('?')
        if idx == -1:
            return None

        oldpath = request.path
        newpath = oldpath[0:idx]
        try:
            url = resolve(newpath)
        except NoReverseMatch:
            return None

        request.path = newpath
        request.GET = QueryDict(oldpath[idx+1:])
        response = url.func(request, *url.args, **url.kwargs)
        response['Link'] = '<%s>; rel="canonical"' % (oldpath,)
        return response
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...