My django-admin page is located at
Suppose there are 3 users in my website.
If anyone of these three users tries to access this link http://127.0.0.1:8000/admin/, 1st and 2nd can access it. And End User is not able to access it. Till this, it is fine.
What I want is to do is to show Error 404 to End User. He/She should never know that this link is for admin page. Moreover, if anyone is not logged in, they should also see same 404 Page.
I have referred this link but it takes me to another default page.
PFA for the same
PS: I am using Signin With Google, so it should not redirect me there.
I am trying this since 3 continous days, so any help is highly appreciated. Thanks in advance.
Django-Version: 3. 0. 5
You first need to make a custom decorator that would give a 404 if the user is not a staff:
from django.http import Http404
from functools import wraps
def staff_required(func):
@wraps(func)
def wrapper(request, *args, **kwargs):
if request.user.is_staff:
return func(request, *args, **kwargs)
raise Http404()
return wrapper
Next we will use this decorator as described in your linked question,:
from django.contrib import admin
admin.site.login = staff_required(admin.site.login)
urlpatterns = [
path('admin/', admin.site.urls),
]
Edit: Above method was a bit hacky it would show the login pages url to the user even if it gives a 404 error. It would be better to make a custom admin site class and use it. The admin site has a method admin_view
which decorates the admin views which we shall override. We shall do this in the file admin.py
in the projects main app (let's say the project is named myproject
)
from functools import update_wrapper
from django.contrib import admin
from django.http import (
Http404, HttpResponseRedirect,
)
from django.urls import reverse
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
class MyAdminSite(admin.AdminSite):
def admin_view(self, view, cacheable=False):
def inner(request, *args, **kwargs):
if not self.has_permission(request):
if request.path == reverse('admin:logout', current_app=self.name):
index_path = reverse('admin:index', current_app=self.name)
return HttpResponseRedirect(index_path)
raise Http404()
return view(request, *args, **kwargs)
if not cacheable:
inner = never_cache(inner)
# We add csrf_protect here so this function can be used as a utility
# function for any view, without having to repeat 'csrf_protect'.
if not getattr(view, 'csrf_exempt', False):
inner = csrf_protect(inner)
return update_wrapper(inner, view)
Now we need to replace the default admin site with our custom admin site. To do this we will follow Overriding the default admin site [Django docs]:
In the projects main app's apps.py
file (assuming project to be named myproject
):
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
Now in settings.py
we will replace 'django.contrib.admin'
with our own config class:
INSTALLED_APPS = [
...
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]