Django/authentification: how to make login page = home page? - django

I develop Django web app using Django authentification backend.
It works without having to define any views or forms, only template to 'bootstrap' it.
But I would like to change 'navigation' url and probably 'redesign' template using django-crispy-form.
But the first step is make user directly access Login page when the 'root' url (https://<my_domain>/) is enter in the navigation adress bar.
Currently, user access home page of my web app that contain a login button that redirect to https://<my_domain>/registration/login
Do I need to override all authentification views (and forms for design) and change url as needed?
Or is there an easiest way, maybe using settings.py to make user redirect to login page from root url?
project
- app
- core
- settings
- base.py
- ...
- views.py
- urls.py
- app1
- forms.py
- views.py
- templates
- app1
- registration # <= currently no forms.py nor views.py
- templates
- registration
- login.html
- password_change_done.html
- ...
- static
- templates
- layout
- base.html
- home.html
core/urls.py
urlpatterns = [
path('', views.home, name='home'), # <= 'root' url
# path('registration/', include('registration.urls')), # <= registration views override
path('registration/', include('django.contrib.auth.urls')),
]
core/settings.py
LOGIN_URL = 'home'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'login'

You cannot have that:
LOGIN_URL = 'home'
Use classic solution:
LOGIN_URL = 'login'
And then use decorator mentioned by #AnkitTiwari if you operate in Function Based Views just on top on home view:
#login_required
def home_view(request):
Or LoginRequiredMixin in Class Based Views:
from django.contrib.auth.mixins import LoginRequiredMixin
class HomeView(LoginRequiredMixin, View):

Related

Replace Django Admin Login page

I need to replace the Django Admin Login page. The reason for that is that I've added some extra authentication at my own login page, however, I don't know how to override the login on the admin site.
Here is the solution. Inside urls.py, add the path to the new login page above your admin URLs like this
path('admin/login/', login_view, name='new_admin_login'), # login_view is the custom login view
path('admin/', admin.site.urls),
Creating a custom AdminSite is the Django way of doing such things. Specifically, in your case set the AdminSite.login_form
from django.contrib.admin import AdminSite
from django.contrib.auth.forms import AuthenticationForm
from django.urls import path
class CustomAuthenticationForm(AuthenticationForm):
# override the methods you want
...
class CustomAdminSite(AdminSite):
login_form = CustomAuthenticationForm
admin_site = CustomAdminSite()
urlpatterns = [
path("admin/", admin_site.urls),
]

How to redirect from a view in one app to a view in another?

I am trying to build a job-board type of website. Right now I have user authentication (login, logout, register, password change, etc) in one app (account) and the job model and all other views/templates in another app(job).
To have the user log in, I used the views found in django.contrib.auth(this is account/urls.py):
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name = 'login'),
]
In the job app I have created a urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('dashboard/', views.dashboard, name = 'dashboard'),
]
Upon logging in, I would like the user to be redirected to this dashboard URL/view found in the job app. How can I do this? I know that if I just put the dashboard view/url into the account app all I would need to do is add this to settings.py:
LOGIN_REDIRECT_URL = 'dashboard'
But, how can I redirect to a view in another app?
Final note: I separated this into two apps in the first place because I've read that is good practice, but am not sure if it's needed here.
Test this:
LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
in settings.py:
LOGIN_REDIRECT_URL = reverse_lazy('job:dashboard')
This only works for redirection once logged in.
[settings.py]:
LOGIN_REDIRECT_URL = 'dashboard'
If you want to redirect urls from any app to another, you must use static tags.
[file.html]
{% load static %}
and then:
<a href="{% url 'dashboard' %}">

How to set custom admin login URL in Django Admin on session timeout?

I wrote a Django app which has an external authentication system reacheable at some URL (say, https://.../myproject/login). This is working well.
However, when the session expires, the user gets redirected to the default login url which is https://.../myproject/admin). I'd like to change the behavior of the app so if the session expires, the user should be redirected to https://.../myproject/login and only use the /admin login when explicitly opened.
Is there a built-in way to do this in Django?
Django admin redirects the users to /admin/login when the session is expired or session is missing.
There are several ways to redirect users to https://.../myproject/login instead of https://.../myproject/admin/login.
Approach 1:
Override the view of myproject/admin/login URL with the view of myproject/login.
Let's say that myproject/login uses LoginView to render external system's login page, then add url(r'^admin/login/?$', LoginView.as_view(), name='admin:login') just above url(r'^admin/', include(admin.site.urls)) in myproject/myproject/urls.py
urlpatterns = [
url(r'^admin/login/?$', LoginView.as_view(), name='admin:login'),
url(r'^admin/', include(admin.site.urls)),
]
Pros:
Render the external system's login page instead of default Django admin login page on /myproject/admin/login
Cons:
The URL still points to myproject/admin/login
No way to access the default admin login page
Approach 2:
Override the view of myproject/admin/login url and redirect the user to myproject/login
Lets create a new view AdminLoginView then add url(r'^admin/login/?$', AdminLoginView.as_view(), name='admin:login') just above url(r'^admin/', include(admin.site.urls)) in myproject/myproject/urls.py
from django.core.urlresolvers import reverse
class AdminLoginView(TemplateView):
def get(self, request, *args, **kwargs):
"""
Assuming the name of the external system's login url is "login"
"""
return HttpResponseRedirect(reverse('login'))
urlpatterns = [
url(r'^admin/login/?$', AdminLoginView.as_view(), name='admin:login'),
url(r'^admin/default-login/?$', admin.site.login, name='default-admin-login'),
url(r'^admin/', include(admin.site.urls)),
]
Pros:
The URL changes to myproject/login
Cons:
You have to add extra code for the default login page.
I would recommend approach 2 to solve the problem mentioned in the question.
Thanks.
You can use LOGIN_URL and LOGOUT_REDIRECT_URL
https://docs.djangoproject.com/en/2.2/ref/settings/#login-url
Redirect to myproject/login for login (Default redirects to /accounts/login/)
LOGIN_URL = '/myproject/login/'
Redirect to the login page after log out (Default to None).
LOGOUT_REDIRECT_URL = '/myproject/login/'
IMO the best possible solution is to override the function for login view.
To do this add these lines of code in your urls.py containing the 'admin/'
# urls.py
def login(request):
if request.user and request.user.is_authenticated and request.user.is_active and request.user.is_staff:
return HttpResponseRedirect(reverse('admin:index', current_app='admin'))
else:
return HttpResponseRedirect(reverse('index', current_app='your_app_name'))
admin.site.login = login
# The lines below probably exist
# urlpatterns = [
# path('admin/', admin.site.urls),
# path('', include('your_app.urls')),
# ]

Login Required Django Classed Based View

Totally beginner question.
I have this view in my app Foo:
class PaymentsView(LoginRequiredMixin, CreateView):
login_url = '/login/'
redirect_field_name = 'redirect_to'
# -- Omitted ...
I have read the django documentation but I didn't see where to put my file "login.html" and how can I set the url for that. When I run the code show the 404 error.
Setting login_url will redirect to a URL within your project, which is then handled by URL Dispatcher. You'll need to include a path to that URL within your URLConf, just like you would with any other URL:
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.login),
]
You'll then need to write a view to handle the login. Django provides pre-written views and URL patterns that handle this with its login system.

Does using Django "is_superuser" require additional URL?

I'm creating an administrative interface/dashboard for a Django 1.7 project. Instead of creating a new admin application from scratch, I'm trying to use Django's built-in admin site. I have "root" (superuser) and "reviewer" (non-superuser) staff accounts. Both accounts are in the default "admin" group. Both accounts can log in to the admin site but some pages are accessible by both the root and reviewer accounts while access to others is limited to the superuser. I've created the two following views:
# mysite/apps/admin/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import user_passes_test
#user_passes_test(lambda u: u.is_staff)
def all_admins(request, template):
return render(request, template)
#user_passes_test(lambda u: u.is_superuser)
def superuser_only(request, template):
return render(request, template)
The problem I'm running into is that if I log is using the reviewer account and click the anchor for the "superuser_only" page, I get the following error:
Page not found (404)
Request Method: GET
Request URL: http://localhost:8001/accounts/login/?next=/admin/super/
Using the URLconf defined in conf.urls, Django tried these URL patterns, in this order:
^admin/
^admin/all_admins/$ [name='all-admins']
^admin/super/$ [name='superuser-only']
The current URL, accounts/login/, didn't match any of these.
Is there something else I need to do to implement this superuser-only view and template so that this error doesn't occur if the reviewer clicks the link?
I followed the Django docs instructions and created my own copies of Django's base.html, base_site.html, and index.html templates in my mysite/apps/admin/templates/admin directory and then added the "all_admins" and "superuser_only" anchors to the bottom of the index.html page.
Here are my files:
# part of mysite/mysite/settings.py
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'apps/admin/templates'),
os.path.join(BASE_DIR, 'apps/admin/templates/admin'),)
# mysite/mysite/urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^admin/all_admins/$',
'apps.admin.views.all_admins',
{'template': 'all_admins.html'},
name='all-admins'),
url(r'^admin/super/$',
'apps.admin.views.superuser_only',
{'template': 'superuser_only.html'},
name='superuser-only'),
)
Then user doesn't pass the test django redirects it to the login page. Defult url for this page is /accounts/login/. Set the LOGIN_URL setting to the admin's login page:
LOGIN_URL = 'admin:login'
Or, if you have non-staff users on the site, set the auth urls in the urls.py:
url('^accounts/', include('django.contrib.auth.urls')),
But this will require you to create several templates (login, logout, change password etc.)
UPDATE: If you want to show a message in the login page then you can create the custom login template for admin. Add this line to your urls.py:
admin.site.login_template = 'my_login.html'
And then create my_login.html template which is extended from admin/login.html:
{% extends 'admin/login.html' %}
{% block content %}
{% if user.is_staff %}
<p class="errornote">You need to be a superuser to access that page.</p>
{% endif %}
{{ block.super }}
{% endblock %}
UPDATE 2: If you don't want to change site-wide LOGIN_URL or implement auth by including django.contrib.auth.urls in your urls.py then you can pass login_url parameter to the #user_passes_test decorator:
#user_passes_test(lambda u: u.is_superuser, login_url='/admin/login/')
def superuser_only(request, template):
return render(request, template)