4

我正在尝试构建一个 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 请求处理的了解太不成熟,无法评估这一点。

4

3 回答 3

4

您是否考虑过Redirects应用程序而不是您正在采取的方法?

它不会隐藏路径 /foo/ 的别名来返回视图 bar(),但它会将 /foo/ 重定向到 /bar/

于 2010-11-22T15:34:14.727 回答
2

(作为答案发布,因为评论似乎不支持换行符或其他标记)

感谢您的建议,我对修改请求属性也有同样的感觉。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_routedROUTED_TO(而不是路由自)部分不是更好的解决方案吗?

然后,依赖于原始路径的代码可以使用 META 中的该密钥。

使用 URLConfs 是不可能的,因为这种别名旨在使最终用户能够配置自己的 URL,假设最终用户无法访问代码库或不知道如何编写自己的 URLConf。

尽管可以编写一个将用户可读可编辑文件(例如 XML)转换为有效 Django url 的函数,但感觉使用数据库记录可以更动态地生成别名(其他对象定义自己的别名)。

于 2010-11-24T11:04:50.197 回答
1

很抱歉发布 necro-post,但我只是在搜索答案时发现了这个线程。我的解决方案似乎更简单。也许a)我依赖于较新的django功能或b)我错过了一个陷阱。

我遇到了这个问题,因为有一个名为“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
于 2012-11-13T06:45:54.350 回答