Hi,
Problem
I noticed that for slug with non-ascii characters, I have problem redirecting them.
In the server logs, I will see many status 301, then browser returns The page isn’t redirecting properly
Code
This return http.HttpResponsePermanentRedirect(obj_url)
is the cause.
# view.py
class CanonicalDetailView(generic.DetailView):
"""
A DetailView which redirects to the absolute_url, if necessary.
https://stackoverflow.com/questions/6456586/redirect-from-generic-view-detailview-in-django
"""
def get_object(self, *args, **kwargs):
# Return any previously-cached object
if getattr(self, "object", None):
return self.object
return super(CanonicalDetailView, self).get_object(*args, **kwargs)
def get(self, *args, **kwargs):
# Make sure to use the canonical URL
self.object = self.get_object()
obj_url = self.object.get_absolute_url()
breakpoint()
if self.request.path != obj_url:
return http.HttpResponsePermanentRedirect(obj_url)
return super(CanonicalDetailView, self).get(*args, **kwargs)
class PersonDetailView(CanonicalDetailView):
model = Person
...
Here is the specific debug I did using breakpoint()
(Pdb) self.object
<Person: FRANÇOIS PINAULT>
(Pdb) self.object.get_absolute_url()
'/people/84a4f91f-6e56-4e0b-a61f-7207cb1fafb4/fran%C3%A7ois-pinault/'
(Pdb) self.request.path
'/people/84a4f91f-6e56-4e0b-a61f-7207cb1fafb4/françois-pinault/'
(Pdb) obj_url
'/people/84a4f91f-6e56-4e0b-a61f-7207cb1fafb4/fran%C3%A7ois-pinault/'
As you can see, FRANÇOIS PINAULT
contains non-ascii character. And self.request.path
!= obj_url
, that is why http.HttpResponsePermanentRedirect(obj_url)
keeps looping and eventually fail.
# models.py
from django.utils.text import slugify
class Person(BasePublicContribute):
...
uuid = models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
unique=True,
)
slug = models.SlugField(
allow_unicode=True,
editable=False,
)
...
def get_absolute_url(self):
return reverse(
"person:detail_slug", kwargs={"slug": self.slug, "uuid": self.uuid}
)
...
# urls.py
path(
"people/<uuid:uuid>/<str:slug>/", PersonDetailView.as_view(), name="detail_slug"
)
Is there anyway we can make reverse
method return non-ascii characters? I tried below which don’t work
# models.py
def get_absolute_url(self):
return reverse(
"person:detail_slug", kwargs={"slug": slugify(self.slug, allow_unicode=True,), "uuid": self.uuid}
)
Thanks!