Create a Django App with Login-Restricted Pages
Now only authorized users will see your app pages
INTRODUCTION
Sometimes you might want to create a Django app whose pages can be accessed by anyone on the internet. Other times, you have sensitive information to preserve and it is necessary that only authenticated users can open and consult some or all pages. Once again, Django comes to the rescue with its built-in resources, which make it a lot easier to build applications partially or totally restricted to authorized users.
In this tutorial, I will show you how to do that by using the Films CRUD app I created in this former tutorial of mine:
Thus, I invite you to clone this GitHub repository and follow its README.md
instructions, so that you can have the Films CRUD app up and running on your machine. After you make the project run locally, your folder structure will look like this (__pycache__
folders are not displayed here):
We will modify some of these files to make all the app pages restricted to authorized users at a first moment; then we will leave this restriction only for the pages where modifications to the database are made (by creating, updating or deleting a film).
PART 1: MAKE ALL PAGES RESTRICTED
1. Create a superuser for your Films app, if you have not done that yet.
python manage.py createsuperuser
If you login to the admin area (http://localhost:8000/admin
) with this new superuser, you can access the Users Model (from the django.contrib.auth
default app) and create other users by choosing the correct options in the admin interface.
You could also create new users by writing code that collects information provided by the user on a sign up page and executes function views or class views to save this data into a new instance of django.contrib.auth.models.User
. However, those steps are beyond our scope for this tutorial. I just mentioned them here to give you some directions for future researches, if that topic interests you.
2. In project/urls.py
, insert a new accounts/
route, as shown below:
from django.contrib import admin
from django.urls import path, includeurlpatterns = [
path('', include('films.urls')),
path('admin/', admin.site.urls), # add this:
path('accounts/', include('django.contrib.auth.urls')),
]
Notice how this new route connects to some builtin Django resources already available in django.contrib.auth.urls
. Actually, if you open your virtual environment folder, follow the path Lib/django/contrib/auth
, and open the urls.py
file inside it, you will see the routes login/
and logout/
, with calls to their respective customized Class-based Views. Those are the two routes that will implement Django’s authentication magic in our project.
3. Create a templates/registration
folder:
mkdir templates/registration
4. Create the following files and fill them with the content available in the links below:
templates/registration/login.html
(content here);templates/registration/logged_out.html
(content here).
On the templates, notice the presence of the next
query parameter. In fact, this parameter is a necessary one when the routes accounts/login
and accounts/logout
are accessed since it tells Django where to go after logging in or out.
5. Modify films/views.py
by importing the LoginRequiredMixin
Class and making FilmsBaseView
inherit from it. This will make all other Film View Classes inherit LoginRequiredMixin
by extension too. Keep the other lines of code not shown here without changes.
(...)# add this import:
from django.contrib.auth.mixins import LoginRequiredMixin# add LoginRequiredMixin to FilmBaseView
class FilmBaseView(LoginRequiredMixin, View):
model = Film
fields = '__all__'
success_url = reverse_lazy('films:all')(...)
Now stop the server, run it again, and try accessing the address http://localhost:8000/films/create
, which is the route to create a new film. If all the code above is correctly built, you will not be able to access this page now, but you will be redirected to the login page instead. Notice also how the next
query parameter is set in the URL and has /films/create/
as its value, indicating that Django will go to this page after a successful login.
Now you just need to insert your correct login information. After you are logged in, you will be able to navigate through the app pages again without restrictions.
By now, if you want to log out, you should access http://localhost:8000/accounts/logout
on your browser. However, this is not a very practical procedure, and it would be nice to have a link to do this operation more naturally in our app. So, we will add a new link on the navigation bar in templates/base.html
, which will run a conditional statement with the user.is_authenticated
method and check if the user is logged in. If that is the case, then the app will show a logout link.
6. Change the content of templates/base.html
to the HTML code provided here. Notice the new {%if user.is_authenticated %}
structure on the navbar code. Use this new link to log out when necessary.
PART 2: MAKE ONLY SOME PAGES RESTRICTED
Now we will leave the restricted access only for pages where you can update, create or delete a film. Actually, this will be a super easy modification: we just need to remove the LoginRequiredMixin
from our FilmBaseView
and place it instead in the views that we want to be restricted (the last three ones).
7. Make the following modifications to films/views.py
. We are reproducing below the whole code after it has been modified:
Important: make LoginRequiredMixin
the first class inherited by FilmCreateView
, FilmUpdateView
, and FilmDeleteView
.
FINAL REMARKS
And that is it! As we can notice, after we have all the login/logout structure ready (with the specific routes and the respective templates inside the registration
folder), we only need to pass the LoginRequiredMixin
class to the Class Views we want to be restricted to authorized users, and Django does all the remaining work for us.
In addition, in this second scenario with access restrictions in just some pages, we could make resources like the update and delete links or the create new button to be displayed only if the current user is logged in. If you want to do these changes, just put the above links and button inside a conditional statement with the {%if user.is_authenticated %}
template tag structure. Now only authenticated users will be able to see them.
Thank you so much, dear reader, for having honored my text with your time and attention.
Happy coding!