djangomedialogin-required

Django, LoginRequiredMiddleware, login, and media


in a Django 5.2 application I discovered LoginRequiredMiddleware. It's a great system. However, I have some problems with the media.

When a url has the @login_not_required() decorator, it's impossible to display uploaded images.

in the console, when the page is loaded, django considers this as a next_url.

[19/Apr/2025 08:11:34] "GET /media/identity/background.jpg HTTP/1.1" 302 0
[19/Apr/2025 08:11:34] "GET /?next=/media/identity/background.jpg HTTP/1.1" 200 3062

If the user is logged in, it works fine by declaring the images downloaded with MEDIA_URL like the examples below. If the user is anonymous, then the image is in error.

<style>
    body{
        background-image: url("{{ MEDIA_URL }}{{ identity.background }}") !important;
    }
</style>

<img src="{{ MEDIA_URL }}{{ identity.logo }}" style="width: auto; height: 100px;">

#settings.py
# Media files 
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_URL = "/media/"

Do you have any idea how to display the media?

I've started to make a custom middelware but that's not the point.

urlpatterns = [
    #path("", LoginView.as_view(template_name="lnr/login.html", redirect_authenticated_user=True), name="home"),
    path("", login_not_required(CustomLoginView.as_view()), name="home"),
    # path("", core_views.login, name="home"),
    path("about/", brand_views.about, name="about"),
]

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

I tried with different views.class, function, loginView.


@login_not_required
def about(request):
    return render(
        request,
        "lnr/about.html",
    )

class CustomLoginView(LoginView):
    template_name = 'lnr/login.html'

@login_not_required
def login(request):
    return render(request, 'lnr/login.html')

Solution

  • You (probably need) to exempt the media and static files from logging in as well here, so:

    from django.views.static import serve
    
    if settings.DEBUG:
        urlpatterns += static(
            settings.STATIC_URL,
            document_root=settings.STATIC_ROOT,
            view=login_not_required(serve),
        )
        urlpatterns += static(
            settings.MEDIA_URL,
            document_root=settings.MEDIA_ROOT,
            view=login_not_required(serve),
        )

    This will of course expose all the media and static files to a user, which might not be what you intend to do: if a person uploads a file to /media then you typically don't want other people to access that file.

    Usually static files and media files are not served by Django, but by a webserver like Nginx or Apache. In that case, you can enforce authentication by a Django view that is first triggered, and responds with an X-Accel header, and then you let Nginx serve the file.