Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Django Authentication

00:00 In the previous lesson, I showed you the DRF web interface and renderers. In this and the next lesson, I’m going to be talking about the DRF permissions.

00:11 The Django REST Framework has a robust permission mechanism. The most common usage of it is tied to your ViewSets. You can specify permissions at both the request level and at the object level.

00:25 An example of requests would be whether or not you’re logged in. An example of the object is whether or not you are able to look at or change that particular object.

00:36 In order to demonstrate DRF permissions, I’m going to have to set up a whole bunch of Django auth pieces. I’m going to spend this lesson prepping, and the next lesson diving into the actual DRF permissions.

00:50 If you are very comfortable with Django auth logins, creating login screens, and creating accounts, you can skip this lesson and not worry about it.

00:59 If the django.contrib.auth module is new to you, then you might want to stick around. Everything that I show you inside of this lesson is moving towards the fact that I need a couple more accounts than just the admin account.

01:12 I’m going to create an account called indy that has the staff setting set to True, and another account called marion that’s just general usage. Out of the box, Django no longer comes with a login page. In order to be able to play with this and have accounts log in and log out, I’m going to need to create a login page to go with these accounts.

01:33 This lesson is going to be just a short review on how these pieces work. If you want to see details on how to use the Django auth library, this article could be of use to you.

01:45 The first change I want to make isn’t really necessary, but it will make your life a little easier. Inside of Fedora/settings, you’ll find a definition for AUTH_PASSWORD_VALIDATORS.

01:56 This specifies what password validators Django runs when you create an account. Because I’m just going to be messing around and I don’t want to have to deal with this. I’m going to zero all of this out.

02:08 This is generally a bad idea. You’re breaking built-in security. But, you know. It’s just between us friends, so I’m getting rid of that.

02:20 The second thing I need to do is create a login page. That’s going to be rendered as a Django template. In order to do that, I’m going to need a templates/ directory, so I’m going to make that inside of the Fedora project.

02:32 The template itself has to go in a directory called registration/, so inside of the templates/ directory, I’m going to create another directory called registration/.

02:42 Once those directories exist, I’m back into Fedora/settings, and I need to tell Django to look in those directories for some template content.

02:51 Look for the TEMPLATES definition and change the value for the "DIRS" key. It needs to be changed to point to that template directory.

03:01 BASE_DIR is defined near the top of the settings file and specifies where the project exists, so templates/ is relative to that BASE_DIR. If you happen to be using an older version of Django, do note that Django 3 uses the path module.

03:17 This BASE_DIR is defined as a path. In Django 2 and before, this would have been an os.path.join() call. While I’ve got settings open, I also want to make one more change.

03:28 I’m going to tell Django where to go if someone logs in and they aren’t explicitly told to go somewhere. So this is the default definition for a logged in user.

03:39 I’m going to set that to a view called library.

03:46 Django provides views for doing authentication, but does not include them by default, so I’m updating the Fedora/urls file to include the URLs for those views.

03:56 They’re in the contrib.auth module, and I’m going to include them under a path called "accounts/".

04:08 Finally, I need the actual template for the login page. I’m going to create the world’s simplest login HTML. It’s not very pretty, it really just has the form in it, but this will do the job.

04:22 This HTML code goes inside of a file called login.html inside of that newly created templates/registration/ directory. The contrib.auth module automatically looks for a template with this name, and that’s how these pieces are wired together. With all that set up, I’m now ready to use the Django admin to create a couple of accounts. In a window offscreen, I’m running the Django development server, and now I’m going to point the browser at localhost:8000/admin.

04:55 Once again logging in with my super-secret password. And now in order to create two accounts, I’m going to click on the Add button for the Users.

05:05 The first account I’m going to create is for indy. I type in the username and passwords, being grateful that I turned off the validators. And when I hit SAVE, the admin will let me edit this newly created account.

05:18 indy was added successfully. I’m going to scroll down to Permissions,

05:23 make indy staff,

05:29 and save. And you can see that indy has been added. Adding one more user.

05:40 Because I don’t need to make any more changes for marion, I can just scroll down to the bottom and save.

05:49 As you can see here in the listing, indy is staff and marion is not.

05:54 Great. Now that you’ve got those accounts, you’re all set to see how the DRF and permissions actually work—coming up in the next lesson.

Avatar image for Mark R Baker

Mark R Baker on June 28, 2021

I have followed along here very closely, checked it twice, but I keep getting this error, when trying to get to the login page: (I have confirmed several times that the login page is in Fedora/templates/registration/login.html. Any help would be much appreciated.

mark

TemplateDoesNotExist at /accounts/login/
registration/login.html
Request Method: GET
Request URL:    http://127.0.0.1:8000/accounts/login/?next=/books/library/
Django Version: 3.2.4
Exception Type: TemplateDoesNotExist
Exception Value:    
registration/login.html
Exception Location: C:\Users\Asus\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\django\template\loader.py, line 47, in select_template
Python Executable:  C:\Users\Asus\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\python.exe
Python Version: 3.8.10
Python Path:    
['C:\\Users\\Asus\\RP_Dango_REST_Framework\\Fedora',
 'C:\\Program '
 'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\\python38.zip',
 'C:\\Program '
 'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\\DLLs',
 'C:\\Program '
 'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\\lib',
 'C:\\Users\\Asus\\AppData\\Local\\Microsoft\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0',
 'C:\\Users\\Asus\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python38\\site-packages',
 'C:\\Users\\Asus\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python38\\site-packages\\win32',
 'C:\\Users\\Asus\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python38\\site-packages\\win32\\lib',
 'C:\\Users\\Asus\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python38\\site-packages\\Pythonwin',
 'C:\\Program '
 'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0',
 'C:\\Program '
 'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\\lib\\site-packages']
Server time:    Mon, 28 Jun 2021 00:20:41 +0000
Avatar image for Christopher Trudeau

Christopher Trudeau RP Team on June 28, 2021

Hi Mark,

It can be a bit of a challenge to debug these things over message forum. As I’m sure you’ve figured out, that means it can’t find the template. The first thing I would do is look at the error message in the web browser. If you’ve DEBUG=TRUE on, you’ll get more information than the exception stack trace. Part of the error message is a list of all the directories where Django is looking for templates. Double check that that list contains your project templates directory.

If it doesn’t, that means your TEMPLATES value in settings.py is incorrect. The example in the course uses Django 3.1, you’re using 3.2, that should be ok. As of Django 3.1 the mechanism for specifying paths in settings.py moved from os.path to pathlib, make sure you’re using pathlib.

If your TEMPLATES setting is correct then I’d look for spelling errors in the name of the directory and filename. Seeing as the view in this case is part of the admin package, it isn’t your code calling the template, which means it has to be the name or directory structure of the file itself.

Hope this helps.

Avatar image for Mark R Baker

Mark R Baker on June 28, 2021

Hello Chris, Thank you for the help. The path part of the Fedora/settings.py looks like this:

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

I have checked the file path several times for spelling errors. Here is the templates section of the same Fedora/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / "templates"],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

I cannot seem to insert the file structure, but the login.html file is definitely placed here: Fedora/templates/registration/login.html

If you see anything amiss, I would really appreciate the help.

Cheers, Mark

Avatar image for Mark R Baker

Mark R Baker on June 28, 2021

I figured it out! Thanks for your help. I have somehow set up the file structure such that there is a folder called Fedora and then inside that another folder called Fedora; the latter contains the main folders and the other apps. So, I had to change the DIRS to

'DIRS': [BASE_DIR / "Fedora/templates"],

It works now.

Thanks for your help. cheers, Mark

Avatar image for Christopher Trudeau

Christopher Trudeau RP Team on June 29, 2021

Hi Mark,

That “Fedora/Fedora” structure is a Django thing. When you create a new Django project it will always create the double structure. The second folder is generally for configuration files. That’s where you find the project level settings and urls files. You generally don’t put your template directory in there, but in the first directory.

Here is a snapshot of my file structure for the project (it might not exactly match, I may have touched things as I was making the course, but it should be close enough to get the picture):

$ tree Fedora
Fedora/
├── Fedora
   ├── __init__.py
   ├── asgi.py
   ├── settings.py
   ├── urls.py
   └── wsgi.py
├── api
   ├── __init__.py
   ├── apps.py
   ├── migrations
      └── __init__.py
   ├── models.py
   ├── urls.py
   └── views.py
├── artifacts
   ├── __init__.py
   ├── admin.py
   ├── apps.py
   ├── fixtures
      └── artifacts.json
   ├── migrations
      ├── 0001_initial.py
      └── __init__.py
   ├── models.py
   ├── serializers.py
   ├── urls.py
   └── views.py
├── books
   ├── __init__.py
   ├── admin.py
   ├── apps.py
   ├── fixtures
      ├── accounts.json
      └── books.json
   ├── migrations
      ├── 0001_initial.py
      └── __init__.py
   ├── models.py
   ├── serializers.py
   ├── urls.py
   └── views.py
├── db.sqlite3
├── manage.py
├── people
   ├── __init__.py
   ├── admin.py
   ├── apps.py
   ├── fixtures
      └── people.json
   ├── migrations
      ├── 0001_initial.py
      └── __init__.py
   ├── models.py
   ├── serializers.py
   ├── urls.py
   └── views.py
├── requirements.txt
├── templates
   └── registration
       └── login.html
└── vehicles
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── fixtures
       └── vehicles.json
    ├── migrations
       ├── 0001_initial.py
       └── __init__.py
    ├── models
       ├── __init__.py
       ├── tools.py
       └── vehicles.py
    ├── serializers
       ├── tools.py
       └── vehicles.py
    ├── urls.py
    └── views
        ├── tools.py
        └── vehicles.py

20 directories, 60 files
Avatar image for Martin Breuss

Martin Breuss RP Team on June 30, 2021

@Mark you can also check out the lesson on Django’s Double-Folder Structure in the Django portfolio course, where we discuss this topic in detail.

Avatar image for Narendrakumar Ratibhai Patel

Narendrakumar Ratibhai Patel on Aug. 10, 2024

while i pressed logout from book

127.0.0.1:8000/accounts/logout/

I got “This page isn’t workingIf the problem continues, contact the site owner. HTTP ERROR 405”

Please suggest solution

Avatar image for Christopher Trudeau

Christopher Trudeau RP Team on Aug. 10, 2024

Hi Narendrakumar,

What version of Django are you using? The more recent versions have removed the ability to use logout links and you now have to use a button.

See here for more info:

stackoverflow.com/questions/77690729/django-built-in-logout-view-method-not-allowed-get-users-logout

Become a Member to join the conversation.