The TLDR Version
You shouldn't really need to use set_urlconf in your middleware. You are free to set request.urlconf without worrying about threads though.
For each request that django processes, it will either use ROOT_URLCONF or the value of request.urlconf if it has been set in the middleware, to decide what urlconf to use. For this reason you shouldn't need to use set_urlconf. Setting request.urlconf is the recommended way.
How it works
In fact, under the hood, after a request has passed through the middleware, django calls this function, to decide which urlconf to use, so if request.urlconf is set, then any calls to set_urlconf in the middleware will be irrelevant anyway:
# django.core.handlers.base.py
def resolve_request(self, request):
if hasattr(request, 'urlconf'):
urlconf = request.urlconf
set_urlconf(urlconf)
resolver = get_resolver(urlconf)
Checkout how django proceeses a request from the official docs for more info.
Thread safety of set_urlconf
Also note that the implementation of set_urlconf is thread-safe:
# django.urls.base.py
# Overridden URLconfs for each thread are stored here.
_urlconfs = Local()
def set_urlconf(urlconf_name):
"""
Set the URLconf for the current thread (overriding the default one in
settings). If urlconf_name is None, revert back to the default.
"""
if urlconf_name:
_urlconfs.value = urlconf_name
else:
if hasattr(_urlconfs, "value"):
del _urlconfs.value
(That is to say, it only affects the current thread.)