现在,当打开url时(不带斜杠-example.com/blog
),将在末尾自动添加一个斜杠(存在301
重定向)。问题是,我能以某种方式做到这一点,以便首先检查该页面是否存在(不带斜杠-example.com/blog
)。如果是这样,请打开它。如果不是,则检查页面是否存在斜线(仅不包含301
-example.com/blog/
)。如果是这样,则重定向301
,否则,则重定向404
。
现在,即使没有页面(example.com/blog
),也将在第一个末尾添加斜杠(example.com/blog/
),301
重定向go,然后只有{{1}引发错误。在这种情况下,必须立即抛出404
错误,而无需进行404
重定向。
301
被重写如下。
dispatch
这现实吗?
我认为是写def is_normal_slash_count(url):
temp_url = url
slash_count = 0
while temp_url.endswith('/'):
slash_count += 1
temp_url = temp_url[:-1]
return (slash_count == 1, slash_count)
def replace_bad_slash(url, slash_count):
if slash_count == 2:
return url.replace('//', '/')
return url.replace('/'*(slash_count-1), '')
def normalize_url(url):
if len(url) > 1:
if not url.endswith('/'):
return url + '/'
# replace the url like /contacts//// to /contacts/
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
url = replace_bad_slash(url, slash_count)
return url
def is_bad_url(url):
if len(url) > 1:
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
return True
return False
class RedirectMixinView:
def dispatch(self, *args, **kwargs):
url = self.request.path
redirect_setting = RedirectSettings.objects.filter(url_from=url).first()
if redirect_setting:
return redirect(redirect_setting.url_to, permanent=True)
if is_bad_url(url):
return redirect(normalize_url(url), permanent=True)
return super(RedirectMixinView, self).dispatch(*args, **kwargs)
的方向。
已更新
projects.urls
middleware
pages.urls
url(r'^page/', include('pages.urls')),
测试
url(r'^$', PageView.as_view(), name='page'),
我尝试过try:
resolve('/page/')
except:
raise Http404
return redirect('/page/')
答案 0 :(得分:2)
首先请确保在settings.py中将APPEND_SLASH
设置为False
。这将禁用自动301重定向到带有斜杠的URL。
然后使用resolve()
来检查重定向前是否存在带有斜杠的URL。在处理response
状态码为404的情况的Middleware类中执行此操作。
from django.urls import resolve
try:
resolve(url_with_slash)
except Resolver404:
raise Http404
return redirect(url_with_slash)
请注意,如果路径与resolve(url)
相匹配,则url
不会引发异常,即使视图之后可能仍会引发404。例如,如果您有一个{ {1}}用于对象的pk在URL中的对象。假设您有 / objects / DetailView
/ 作为显示对象的路径,然后是URL / objects / 4 / 即使pk = 4的对象不存在,em> 也将始终匹配。重定向后,视图仍会显示404。
因此,如果您确实还想捕获那些404,则可以实际调用视图函数来检查响应:
<pk>
答案 1 :(得分:2)
RedirectMixinView
中删除LandingView
。CommonMiddleware
。RedirectMiddleware
添加到中间件的列表(最好在顶部)。RedirectMiddleware
该代码与 @dirkgroten (他的大部分贡献)共同编写。
import re
from django.http import HttpResponsePermanentRedirect
class RedirectMiddleware(object):
response_redirect_class = HttpResponsePermanentRedirect
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
path = re.sub("/+", "/", request.path)
if response.status_code == 404:
if not path.endswith('/'):
request.path = path # to force using the cleaned path
else:
request.path = path[:-1] # to force using the cleaned path
try:
full_path = request.get_full_path(force_append_slash=True) # add the slash, keeping query parameters
r = resolve(full_path)
new_response = r.func(request, args=r.args, kwargs=r.kwargs)
if new_response.status_code == 200:
return redirect(full_path)
except Resolver404:
pass # this will fall through to `return response`
# Add the Content-Length header to non-streaming responses if not
# already set.
if not response.streaming and not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))
return response
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) $scheme://$host/$1 permanent;
}
# merge_slashes off;
它可以满足您的需要,并且如果存在此页面,也可以删除重复的斜杠。