Create a Django App with Login-Restricted Pages

Now only authorized users will see your app pages

Fabrício Barbacena
Towards Data Science

--

Photo by Dan Nelson on Unsplash

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):

Image by Author

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, include
urlpatterns = [
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:

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!

--

--

Python and Django Developer • Data Analyst • BI Consultant • Data Science • Data Engineering • https://linktr.ee/fabriciobarbacena