Skip to content

Commit 66652bc

Browse files
humitosericholscher
authored andcommitted
Revert commit 88c7640
This commit reverts 88c7640 from PR #6430 We found a problem with `from_url` that are smaller than 5 char length. I'm reverting this here and adding a new commit that will workaround this problem.
1 parent 959d387 commit 66652bc

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

readthedocs/redirects/querysets.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Queryset for the redirects app."""
22

33
from django.db import models
4+
from django.db.models import Value, CharField, IntegerField, Q, F, ExpressionWrapper
5+
from django.db.models.functions import Substr, Length
46

57
from readthedocs.core.utils.extend import SettingsOverrideObject
68

@@ -25,7 +27,79 @@ def api(self, user=None, detail=True):
2527
return queryset
2628

2729
def get_redirect_path_with_status(self, path, full_path=None, language=None, version_slug=None):
28-
for redirect in self.select_related('project'):
30+
# add extra fields with the ``path`` and ``full_path`` to perform a
31+
# filter at db level instead with Python
32+
queryset = self.annotate(
33+
path=Value(
34+
path,
35+
output_field=CharField(),
36+
),
37+
full_path=Value(
38+
full_path,
39+
output_field=CharField(),
40+
),
41+
42+
from_url_length=ExpressionWrapper(
43+
Length('from_url'),
44+
output_field=IntegerField(),
45+
),
46+
47+
# 1-indexed
48+
from_url_without_rest=Substr(
49+
'from_url',
50+
1,
51+
F('from_url_length') - 5, # Strip "$rest"
52+
output_field=CharField(),
53+
),
54+
55+
# 1-indexed
56+
full_path_without_rest=Substr(
57+
'full_path',
58+
1,
59+
F('from_url_length') - 5, # Strip "$rest"
60+
output_field=CharField(),
61+
),
62+
)
63+
prefix = Q(
64+
redirect_type='prefix',
65+
path__startswith=F('from_url'),
66+
)
67+
page = Q(
68+
redirect_type='page',
69+
path__iexact=F('from_url'),
70+
)
71+
exact = (
72+
Q(
73+
redirect_type='exact',
74+
from_url__endswith='$rest',
75+
# This works around a bug in Django doing a substr and an endswith,
76+
# so instead we do 2 substrs and an exact
77+
# https://code.djangoproject.com/ticket/29155
78+
full_path_without_rest=F('from_url_without_rest'),
79+
) | Q(
80+
redirect_type='exact',
81+
full_path__iexact=F('from_url'),
82+
)
83+
)
84+
sphinx_html = (
85+
Q(
86+
redirect_type='sphinx_html',
87+
path__endswith='/',
88+
) | Q(
89+
redirect_type='sphinx_html',
90+
path__endswith='/index.html',
91+
)
92+
)
93+
sphinx_htmldir = Q(
94+
redirect_type='sphinx_htmldir',
95+
path__endswith='.html',
96+
)
97+
98+
# There should be one and only one redirect returned by this query. I
99+
# can't think in a case where there can be more at this point. I'm
100+
# leaving the loop just in case for now
101+
queryset = queryset.filter(prefix | page | exact | sphinx_html | sphinx_htmldir)
102+
for redirect in queryset.select_related('project'):
29103
new_path = redirect.get_redirect_path(
30104
path=path,
31105
language=language,

0 commit comments

Comments
 (0)