본문 바로가기
DoItDJango

User Authentication

by 자동매매 2023. 4. 17.

Chapter 9: User Authentication

Now that we have a working custom user model we can add the functionality every website needs: the ability to sign up, log in, and log out users. Django provides everything we need for log in and log out but we will need to create our own form to sign up new users. We'll also build a basic homepage with links to all three features so we don't have to type in the URLs by hand every time.

Templates

By default the Django template loader looks for templates in a nested structure within each app. So a home.html template in users would need to be located at users/templates/users/home.html. But a single templates directory within newspaper_-project approach is cleaner and scales better so that's what we'll use.

Let's create a new templates directory and within it a registration directory as that's where Django will look for the log in template.

Command Line

Shape21

(news) $ mkdir templates

(news) $ mkdir templates/registration

Shape22

Now we need to tell Django about this new directory by updating the configuration for 'DIRS' in settings.py. This is a one-line change.

Chapter 9: User Authentication 180

Code

Shape23

  • newspaper_project/settings.py

TEMPLATES = [

{

...

'DIRS': [os.path.join(BASE_DIR, 'templates')], # new

...

}

]

Shape24

If you think about what happens when you log in or log out of a site, you are immediately redirected to a subsequent page. We need to tell Django where to send users in each case. The LOGIN_REDIRECT_URL and LOGOUT_REDIRECT_URL settings do that. We'll configure both to redirect to our homepage which will have the named URL of 'home'.

Remember that when we create our URL routes we have the option to add a name to each one. So when we make the homepage URL we'll make sure to call it 'home'.

Add these two lines at the bottom of the settings.py file.

Code

Shape25

  • newspaper_project/settings.py LOGIN_REDIRECT_URL = 'home' LOGOUT_REDIRECT_URL = 'home'

Shape26

Now we can create four new templates:

Chapter 9: User Authentication 181

Command Line

Shape27

(news) $ touch templates/registration/login.html

(news) $ touch templates/base.html

(news) $ touch templates/home.html

(news) $ touch templates/signup.html

Shape28

Here's the HTML code for each file to use. The base.html will be inherited by every other template in our project. By using a block like {% block content %} we can later override the content just in this place in other templates.

Code

Shape29

<!-- templates/base.html -->

<!DOCTYPE html>

< html >

< head >

< meta charset="utf-8">

< title >{% block title %}Newspaper App{% endblock title %}</ title >

</ head >

< body >

< main >

{% block content %}

{% endblock content %}

</ main >

</ body >

</ html >

Shape30

Chapter 9: User Authentication 182

Code

Shape31

<!-- templates/home.html -->

{% extends 'base.html' %}

{% block title %}Home{% endblock title %}

{% block content %}

{% if user.is_authenticated %}

Hi {{ user.username }}!

< p >< a href="{% url 'logout' %}">Log Out</ a ></ p > {% else %}

< p >You are not logged in</ p >

< a href="{% url 'login' %}">Log In</ a > | < a href="{% url 'signup' %}">Sign Up</ a >

{% endif %}

{% endblock content %}

Shape32

Code

Shape33

<!-- templates/registration/login.html --> {% extends 'base.html' %}

{% block title %}Log In{% endblock title %}

{% block content %}

< h2 >Log In</ h2 >

< form method="post">

{% csrf_token %}

{{ form.as_p }}

Chapter 9: User Authentication 183

< button type="submit">Log In</ button >

</ form >

{% endblock content %}

Shape34

Code

Shape35

<!-- templates/signup.html -->

{% extends 'base.html' %}

{% block title %}Sign Up{% endblock title %}

{% block content %}

< h2 >Sign Up</ h2 >

< form method="post">

{% csrf_token %}

{{ form.as_p }}

< button type="submit">Sign Up</ button > </ form >

{% endblock content %}

Shape36

Our templates are now all set. Still to go are our URLs and views.

URLs

Let's start with the url routes. In our newspaper_project/urls.py file we want to have our home.html template appear as the homepage. But we don't want to build a dedicated pages app just yet, so we can use the shortcut of importing TemplateView and setting the template_name right in our url pattern.

Chapter 9: User Authentication 184

Next we want to "include" both the users app and the built-in auth app. The reason is that the built-in auth app already provides views and urls for log in and log out. But for sign up we will need to create our own view and url. To ensure that our URL routes are consistent we place them both at users/ so the eventual URLS will be /users/login, /users/logout, and /users/signup.

Code

Shape37

newspaper_project/urls.py

from django.contrib import admin

from django.urls import path, include # new

from django.views.generic.base import TemplateView # new

urlpatterns = [

path('admin/', admin.site.urls),

path('users/', include('users.urls')), # new

path('users/', include('django.contrib.auth.urls')), # new path('', TemplateView.as_view(template_name='home.html'),

name='home'), # new

]

Shape38

Now create a urls.py file in the users app.

Command Line

Shape39

(news) $ touch users/urls.py

Shape40

Update users/urls.py with the following code:

Chapter 9: User Authentication 185

Code

Shape41

users/urls.py

from django.urls import path

from .views import SignUpView

urlpatterns = [

path('signup/', SignUpView.as_view(), name='signup'),

]

Shape42

The last step is our views.py file which will contain the logic for our sign up form. We're using Django's generic CreateView here and telling it to use our CustomUserCreationForm, to redirect to login once a user signs up successfully, and that our template is named signup.html.

Code

Shape43

users/views.py

from django.urls import reverse_lazy

from django.views.generic import CreateView

from .forms import CustomUserCreationForm

class SignUpView (CreateView):

form_class = CustomUserCreationForm

success_url = reverse_lazy('login')

template_name = 'signup.html'

Shape44

Ok, phew! We're done. Let's test things out.

Chapter 9: User Authentication 186

Start up the server with python manage.py runserver and go to the homepage at http://127.0.0.1:8000/.

Homepage logged in

We logged in to the admin in the previous chapter so you should see a personalized greeting here. Click on the "Log Out" link.

Homepage logged out

Now we're on the logged out homepage. Go ahead and click on login link and use your superuser credentials.

Log in

Upon successfully logging in you'll be redirected back to the homepage and see the same personalized greeting. It works!

Chapter 9: User Authentication 187

Homepage logged in

Now use the "Log Out" link to return to the homepage and this time click on the "Sign Up" link.

Homepage logged out

You'll be redirected to our signup page. See that the age field is included!

Sign up page

Create a new user. Mine is called testuser and I've set the age to 25. After successfully submitting the form you'll be redirected to the log in page. Log in with your new user and you'll again be redirected to the homepage with a personalized greeting for the

Chapter 9: User Authentication 188

new user.

Homepage for testuser

Everything works as expected.

Admin

Let's also log in to the admin to view our two user accounts. Navigate to:

http://127.0.0.1:8000/adminand …

Admin log in wrong

What's this! Why can't we log in?

Well we're logged in with our new testuser account not our superuser account. Only a superuser account has the permissions to log in to the admin! So use your superuser account to log in instead.

Chapter 9: User Authentication 189

After you've done that you should see the normal admin homepage. Click on Users and you can see our two users: the one we just created and your previous superuser name (mine is wsv).

Users in the Admin

Everything is working but you may notice that there is no "Email address" for our testuser. Why is that? Well, look back at the sign up page at:

http://127.0.0.1:8000/users/signup/

You'll see that it asks for username, age, and password but not an email! However we can easily change it. Let's return to our users/forms.py file.

Currently, under fields we're using Meta.fields which just displays the default settings of username/password. But we can also explicitly set which fields we want displayed so let's update it to ask for a username/email/password by setting it to ('username', 'email',). We don't need to include the password fields because they

Chapter 9: User Authentication 190

are required! However all the other fields can be configured however we choose.

Code

Shape45

users/forms.py

from django import forms

from django.contrib.auth.forms import UserCreationForm, UserChangeForm

from .models import CustomUser

class CustomUserCreationForm (UserCreationForm):

class Meta (UserCreationForm):

model = CustomUser

fields = ('username', 'email', 'age',) # new

class CustomUserChangeForm (UserChangeForm):

class Meta :

model = CustomUser

fields = ('username', 'email', 'age',) # new

Shape46

The Python programming community agrees that"explicit is better than implicit"so naming our fields in this fashion is a good idea.

Now if you try out the sign up page again athttp://127.0.0.1:8000/users/signup/you can see the additional "Email address" field is there.

Chapter 9: User Authentication 191

New sign up page

Sign up with a new user account. I've named mine testuser2 with an age of 18 and an email address of testuser2@email.com. Continue to log in and you'll see a personalized greeting on the homepage.

testuser2 homepage greeting

Then switch back to the admin page–log in using our superuser account to do so–and all three users are on display.

Chapter 9: User Authentication 192

Three users in the Admin

Django's user authentication flow requires a little bit of set up but you should be starting to see that it also provides us incredible flexibility to configure sign up and log in exactly how we want.

Conclusion

So far our Newspaper app has a custom user model and working sign up, log in, and log out pages. But you may have noticed our site doesn't look very good. In the next chapter we'll addBootstrapfor styling and create a dedicated pages app.

'DoItDJango' 카테고리의 다른 글

sendgrid를 통한 메일 전송  (0) 2023.04.18
Chapter 10: Bootstrap  (0) 2023.04.17
Django db.sqlite3 초기화  (0) 2023.04.16
User Accounts  (0) 2023.04.16
Forms  (0) 2023.04.15

댓글