arabic slug show 404

Hi

if i use Arabic slug in localhost that works just fine, but on the server in production any page with Arabic slug well show 404 error, In the same time English slug works.

models.py

    slug = models.SlugField(blank=True, editable=True, allow_unicode=True, null=False, unique=True )

urls.py

from django.urls import path, re_path

from blogs import views

app_name = "blogs"
...
re_path(r'^(?P<slug>[-a-zA-Z0-9 _ءاأإآؤئبتثجحخدذرزسشصضطظعغفقكلمنهويةى٠١٢٣٤٥٦٧٨٩]+)/$', views.BlogDetailView.as_view(),
            name='blog_detail'),
    path('<str:slug>/', views.BlogDetailView.as_view(), name='blog_detail'),

views.py

class BlogDetailView(DetailView):
    model = Blog
    template_name = 'blogs/blogDetails.html'

    def post(self, request, *args, **kwargs):
        year = self.request.POST.get('year_choice', None)
        instance = self.get_object()
        if not year:
            return redirect('blogs:blog_detail', slug=instance.slug)
        return redirect('reports:blog_report', slug=instance.slug, year=year)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        instance = self.get_object()
        year = self.kwargs.get('year')
        reports = Report.objects.filter(blog=instance)
        years = Year.objects.filter(name__gte=str(instance.since), report__in=reports)
        context['years'] = years
        context['year'] = year
        return context

settings.py

ALLOW_UNICODE_SLUGS = True

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '',
        'PASSWORD': '',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'OPTIONS'   : {
              'init_command'  : "SET sql_mode='STRICT_TRANS_TABLES'",
              'charset'       : 'utf8mb4',
          }
    }
}

have you checked you nginx/apache/lighttpd/whatever setup on production? If it works on local/dev and not on production, it looks unlikely it is a django issue. Your safest bet would be to investigate the “odd one out” :slight_smile:

i am with a shared hosting provider with this info:

cPanel Version 106.0 (build 11)
Apache Version 2.4.54
PHP Version 7.4.33
MySQL Version 10.5.18-MariaDB-cll-lve
Architecture x86_64
Operating System linux
Perl Version 5.26.3
Kernel Version 4.18.0-372.9.1.1.lve.el8.x86_64
Python v3.9.12
LiteSpeed Web Server

also i can reach the terminal as USER ( no root )

well then check your apache configuration options and what you can do with it?

You might also want to try writing the slug that you are seeing in a log file to see how it’s being presented to you. It’s possible that the slug is being url-encoded and that you may need to decode it before using it.

here is the line from the error log,

[22/Dec/2022 15:39:42] WARNING [django.request:241] Not Found: /blogs/%D8%A8/

i used one character “ب” to ease the debug.

That definitely looks like the slug is urlencoded. Try decoding it before using it in the view. (You could override get_object to modify self.kwargs['slug'] before calling super. There are other approaches you could take as well.)

1 Like

browsers will send utf-8 characters in encoded form.

so éééé will be sent as %C3%A9%C3%A9%C3%A9%C3%A9

As Ken suggest, you could try to override you get_object method. and do smth similar to this:

from urllib.parse import unquote
unquote('%C3%A9%C3%A9%C3%A9%C3%A9')
# -> 'éééé'
unquote('%D8%A8')
# -> 'ب'

hopefully that works :slight_smile:

Many thanks @KenWhitesell @plopidou :rose: