본문 바로가기
DoItDJango

User Accounts

by 자동매매 2023. 4. 16.

Heroku Config.docx
0.08MB

Chapter 8: Custom User Model

Django's built-inUser modelallows us to start working with users right away, as we just did with our Blog app in the previous chapters. However theofficial Djangodocumentationhighly recommends using a custom user model for new projects. Thereason is that if you want to make any changes to the User model down the road–-for example adding an age field-–using a custom user model from the beginning makes this quite easy. But if you do not create a custom user model, updating the default User model in an existing Django project is very, very challenging.

So always use a custom user model for all new Django projects. But the approach demonstrated in the official documentationexampleis actually not what many Django experts recommend. It uses the quite complex AbstractBaseUser when if we just use AbstractUser instead things are far simpler and still customizable.

Thus we will use AbstractUser in this chapter where we start a new Newspaper app properly with a custom user model. The choice of a newspaper app pays homage to Django's roots as a web framework built for editors and journalists at the Lawrence Journal-World.

Set Up

The first step is to create a new Django project from the command line. We need to do several things:

  • create and navigate into a new directory for our code

  • create a new virtual environment news

Chapter 8: Custom User Model 168
  • install Django

  • make a new Django project newspaper_project

  • make a new app users

We're calling our app for managing users users here but you'll also see it frequently called accounts in open source code. The actual name doesn't matter as long as you are consistent when referring to it throughout the project.

Here are the commands to run:

Command Line

Shape1

  • cd ~/Desktop

  • mkdir news

  • cd news

  • pipenv install django==3.0.1

  • pipenv shell

(news) $ django-admin startproject newspaper_project .

(news) $ python manage.py startapp users

(news) $ python manage.py runserver

Shape2

Note that we did not run migrate to configure our database. It's important to wait until after we've created our new custom user model before doing so given how tightlyconnected the user model is to the rest of Django.

If you navigate tohttp://127.0.0.1:8000you'll see the familiar Django welcome screen.

Chapter 8: Custom User Model 169

Welcome page

Custom User Model

Creating our custom user model requires four steps:

  • update settings.py

  • create a new CustomUser model

  • create new forms for UserCreationForm and UserChangeForm

  • update users/admin.py

In settings.py we'll add the users app to our INSTALLED_APPS. Then at the bottom of the file use the AUTH_USER_MODEL config to tell Django to use our new custom user model

Chapter 8: Custom User Model 170

in place of the built-in User model. We'll call our custom user model CustomUser so, since it exists within our users app we refer to it as users.CustomUser.

Code

Shape3

  • newspaper_project/settings.py

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users.apps.UsersConfig', # new

]

...

AUTH_USER_MODEL = 'users.CustomUser' # new

Shape4

Now update users/models.py with a new User model which we'll call CustomUser that extends the existing AbstractUser. We also include our first custom field, age, here.

Code

Shape5

users/models.py

from django.contrib.auth.models import AbstractUser from django.db import models

class CustomUser (AbstractUser):

age = models.PositiveIntegerField(null=True, blank=True)

Shape6

If you read theofficial documentation on custom user modelsit recommends using AbstractBaseUser not AbstractUser. This needlessly complicates things in my opinion,especially for beginners.

Chapter 8: Custom User Model 171

AbstractBaseUser vs AbstractUser

AbstractBaseUser requires a very fine level of control and customization. We essen-tially rewrite Django. This can be helpful, but if we just want a custom user model that can be updated with additional fields, the better choice is AbstractUser which subclasses AbstractBaseUser. In other words, we write much less code and have less opportunity to mess things up. It's the better choice unless you really know what you're doing with Django!

Note that we use bothnullandblankwith our age field. These two terms are easy to confuse but quite distinct:

  • null is database-related. When a field has null=True it can store a database entry as NULL, meaning no value.
  • blank is validation-related , if blank=True then a form will allow an empty value, whereas if blank=False then a value is required.

In practice, null and blank are commonly used together in this fashion so that a form allows an empty value and the database stores that value as NULL.

A common gotcha to be aware of is that the field type dictates how to use these values. Whenever you have a string-based field like CharField or TextField, setting both null and blank as we've done will result in two possible values for "no data" in the database. Which is a bad idea. The Django convention is instead to use the empty string '', not NULL.

Forms

If we step back for a moment, what are the two ways in which we would interact with our new CustomUser model? One case is when a user signs up for a new account on our

Chapter 8: Custom User Model 172

website. The other is within the admin app which allows us, as superusers, to modify existing users. So we'll need to update the two built-in forms for this functionality: UserCreationFormandUserChangeForm.

Stop the local server with Control+c and create a new file in the users app called forms.py.

Command Line

Shape7

(news) $ touch users/forms.py

Shape8

We'll update it with the following code to extend the existing UserCreationForm and UserChangeForm forms.

Code

Shape9

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 = UserCreationForm.Meta.fields + ('age',)

class CustomUserChangeForm (UserChangeForm):

Chapter 8: Custom User Model 173

class Meta :

model = CustomUser

fields = UserChangeForm.Meta.fields

Shape10

For both new forms we are using theMeta classto override the default fields by setting the model to our CustomUser and using the default fields via Meta.fields which includes all default fields. To add our custom age field we simply tack it on at the end and itwill display automatically on our future sign up page. Pretty slick, no?

The concept of fields on a form can be confusing at first so let's take a moment to explore it further. Our CustomUser model contains all the fields of the default User model and our additional age field which we set.

But what are these default fields? It turns out thereare manyincluding username, first_name, last_name, email, password, groups, and more. Yet when a user signs upfor a new account on Django the default form only asks for a username, email, and password. This tells us that the default setting for fields on UserCreationForm is just username, email, and password even though there are many more fields available.

This might not click for you since understanding forms and models properly takes some time. In the next chapter we will create our own sign up, log in, and log out pages which will tie together our CustomUser model and forms more clearly. So hang tight!

The only other step we need is to update our admin.py file since Admin is tightly coupled to the default User model. We will extend the existingUserAdminclass to use our new CustomUser model.

Chapter 8: Custom User Model 174

Code

Shape11

users/admin.py

from django.contrib import admin

from django.contrib.auth.admin import UserAdmin

from .forms import CustomUserCreationForm, CustomUserChangeForm from .models import CustomUser

class CustomUserAdmin (UserAdmin):

add_form = CustomUserCreationForm

form = CustomUserChangeForm

model = CustomUser

admin.site.register(CustomUser, CustomUserAdmin)

Shape12

Ok we're done! Type Control+c to stop the local server and go ahead and run makemigrations and migrate for the first time to create a new database that uses thecustom user model.

Command Line

Shape13

(news) $ python manage.py makemigrations users

(news) $ python manage.py migrate

Shape14

Superuser

Let's create a superuser account to confirm that everything is working as expected.

Chapter 8: Custom User Model 175

On the command line type the following command and go through the prompts.

Command Line

Shape15

(news) $ python manage.py createsuperuser

Shape16

The fact that this works is the first proof our custom user model works as expected.

Let's view things in the admin too to be extra sure.

Start up the web server.

Command Line

Shape17

(news) $ python manage.py runserver

Shape18

Then navigate to the admin athttp://127.0.0.1:8000/adminand log in.

Admin page

If you click on the link for "Users" you should see your superuser account as well as the default fields of Username, Email Address, First Name, Last Name, and Staff Status.

Chapter 8: Custom User Model 176

Admin one user

We can control the fields listed here via the list_display setting for CustomUserAdmin. Let's do that now so that it displays email, username, age, and staff status. This is a one-line change.

Code

Shape19

users/admin.py

from django.contrib import admin

from django.contrib.auth.admin import UserAdmin

from .forms import CustomUserCreationForm, CustomUserChangeForm from .models import CustomUser

class CustomUserAdmin (UserAdmin):

Chapter 8: Custom User Model 177

add_form = CustomUserCreationForm

form = CustomUserChangeForm

model = CustomUser

list_display = ['email', 'username', 'age', 'is_staff',] # new

admin.site.register(CustomUser, CustomUserAdmin)

Shape20

Refresh the page and you should see the update.

Admin custom list display

Chapter 8: Custom User Model 178

Conclusion

With our custom user model complete, we can now focus on building out the rest of our Newspaper app. In the next chapter we will configure and customize sign up, log in, and log out pages.

'DoItDJango' 카테고리의 다른 글

User Authentication  (0) 2023.04.17
Django db.sqlite3 초기화  (0) 2023.04.16
Forms  (0) 2023.04.15
Blog App  (0) 2023.04.15
텍스트 콘텐츠를 저장하는 모델 만들기  (0) 2023.04.14

댓글