Search code examples
djangoregexurldjango-urlsregex-group

Regex pattern to capture all folders in URL including forward slash


I want to match dynamically created URLs which can have multiple folders. Need some regex pattern for this. For ex.

http://127.0.0.1:8000/api/:user_id/:foldersa/:folders1/
http://127.0.0.1:8000/api/:user_id/:foldersb/:folders2/:folders3/:folders4
http://127.0.0.1:8000/api/:user_id/:foldersc/:folders2/
http://127.0.0.1:8000/api/:user_id/:foldersd/:folders1/:folders2/

so till BASE_URL/api/:user_id/ is common. I can catch user_id but want to catch other params after user_id on a single string variable.
after that, there can be any number of folders and I want to catch them all in one single string variable.
like for first URL string variable caught will be "foldera/folder1/" and for next url string variable will be "folderb/folder2/folder3/folder4" along with fwd slashes.

What regex pattern should I write in urls.py for capturing this folders?
I tried with re_path(r'(?P<user_id>[-\w]+)/(?P<customUrl>(.*?)(?:\/)?$)/.*', customLink, name='customLink'),

but couldn't get it to work.


Solution

  • You can match all but the last optional trailing slash:

    re_path(r'(?P<user_id>[-\w]+)/(?P<custom_url>.*?)/?$', customLink, name='customLink'),

    in the view you can then split the endpoints with:

    def customLink(request, user_id, custom_url):
        endpoints = custom_url.split('/')
        # …

    You can also make use of a path converter:

    # app_name/converters.py
    
    class EndpointsConverter:
        regex = ".*?"
        
        def to_python(self, value):
            return value.split('/')
        
        def to_url(self, value):
            if isinstance(value, str):
                return value
            return '/'.join(value)

    then you can work with a path converter:

    from django.urls import path, register_converter
    from app_name.converters import EndpointsConverter
    
    register_converter(EndpointsConverter, 'endpoints')
    
    urlpatterns = [
        path('<str:user_id>/<endpoints:endpoints>/', customLink, name='customLink'),
        # …
    ]

    this will automatically split (and join) the endpoints by the slashes.