Aula 79 - Loja Online - Personalizando o Model User Default Django
Nós criamos vários modelos:
Product,
Cart,
Account..., mas o
User não, mesmo não tendo criado ele, temos o
modelo User em nosso projeto.
Porque?
Porque o
django já vem com um modelo
User padrão, e é por isso que temos ele no projeto mesmo sem ter criado, ele vem por padrão quando a gente gera um projeto
django.
Ele é um
app que é importado no
django_ecommerce/e_commerce/e_commerce/settings.py dentro da lista
INSTALLED_APPS e vem do
django.contrib.auth.
Você pode estender o
User padrão, ou substituir por um modelo totalmente personalizado.
O que vamos fazer é personalizar esse
User padrão do
django.
Se ao invés de um
eCommerce, fosse um aplicativo
social como o
Twitter, ou
Facebook, faria mais sentido usar os nomes de usuários, poderíamos deixar do jeito que tá e usar o
User padrão do
django.
Mas, vamos personalizar para usar o
email como identificador do usuário ao invés do nome, por fazer mais sentido no caso de um
eCommerce e também para aprender a como customizar o
User padrão do
django.
Teremos
um email único para
uma conta única.
Modelo User Padrão
Por padrão, quando criamos um
projeto django, o
User padrão é ativado no
settings.py do projeto, em
INSTALLED_APPS, onde tem a seguinte string: '
django.contrib.auth'.
Tem muito mais coisas envolvidas no modelo
User padrão do
django, que não tem nos outros modelos que criamos como:
Accounts,
Carts,
Products, etc.
O
model User padrão do
django, lida com a
autenticação,
login, etc. Coisa que os outros modelos não precisam lidar.
O
modelo Product, foi um modelo que criamos e adicionamos alguns campos, criamos um gerenciador de produto, o
ProductManager(), que extendeu o
models.Manager do
django, criamos também o método
__str__().
Um modelo padrão do django, espera muito mais coisas do que apenas extender o
models.Model.
Personalizando o modelo User Default Django
A classe
AbstractBaseUser é a classe que iremos implementar para o
User Model.
Abra o
django_ecommerce/e_commerce/accounts/models.py e faça as seguintes modificações.
django_ecommerce/e_commerce/accounts/models.py
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser
)
class CustomUser(AbstractBaseUser):
pass
class GuestEmail(models.Model):
email = models.EmailField()
active = models.BooleanField(default=True)
update = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.email
Rode a migration com:
python manage.py makemigrations
Veja que foi criado um novo arquivo na pasta
e_commerce/accounts/migrations.
Nesse arquivo, você pode ver que o
User tem os campos que são definidos pelo modelo
User padrão do
django:
id,
password e
last_login.
Agora vamos fazer as seguintes modificações: trocar o nome da classe
CustomUser para
User, rodar de novo:
python manage.py makemigrations
Ele vai perguntar se você quer renomear o
accounts.CustomUser model para
User, é só digitar
y.
Adicionando Campos
Vamos adicionar alguns campos:
active,
staff,
admin e
timestamp.
Diferença entre auto_now_add e auto_now
No
timestamp usamos o
auto_now_add, que só é acionado na criação do usuário, se a gente tivesse algo do tipo
update_at, a gente usaria o
auto_now, ao invés de
auto_now_add e provavelmente teríamos também o
created_at, nele usaríamos o
auto_now_add, como usamos no
timestamp.
Adicionando Métodos
O
modelo User padrão espera alguns
métodos.
Veja na
documentação oficial a lista.
Vamos colocar alguns deles:
__str__(),
get_full_name(),
get_short_name()
Adicionando Propriedades
Algumas propriedades também, usando o
decorator @property:
is_staff(),
is_admin() e
is_active().
Decorator @property
O decorador
@property do Django é usado para definir um método como um atributo de leitura de uma classe.
Ele permite que você acesse o resultado de um método como se fosse um atributo, sem precisar chamar o método com parênteses.
Por exemplo:
class Example:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
Você pode acessar o valor da propriedade
value como se fosse um atributo, sem precisar usar parênteses:
>>>example = Example(10)
>>> example.value
10
Em Django, o decorador
@property é usado para criar propriedades dinâmicas em modelos que podem ser acessadas como se fossem atributos de um objeto de modelo, mas que na verdade são resultados de uma expressão ou método.
Voltando ao código do eCommerce
As modificações estão em
azul.
django_ecommerce/e_commerce/accounts/models.py
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser
)
class User(AbstractBaseUser):
#full_name = models.CharField(max_length=255, blank=True, null=True)
email = models.EmailField(max_length=255, unique=True)
active = models.BooleanField(default=True) # can do login
staff = models.BooleanField(default=False) # staff user, non superuser
admin = models.BooleanField(default=False) #superuser
timestamp = models.DateTimeField(auto_now_add=True)
# confirm = models.BooleanField(default=False)
# confirmed_date = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
# USERNAME_FIELD and password are required by default
REQUIRED_FIELDS = [] # ['full_name'] #python manage.py createsuperuser
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
@property
def is_staff(self):
return self.staff
@property
def is_admin(self):
return self.admin
@property
def is_active(self):
return self.active
class GuestEmail(models.Model):
email = models.EmailField()
active = models.BooleanField(default=True)
update = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.email
Rode novamente o
python manage.py makemigrations
E o
python manage.py migrate
Ele vai dizer que precisa de um valor para o campo email, já que ele não pode ser nulo.
Selecione a opção 1 e digite um email qualquer tipo:
"youremail123@gmail.com"
Coloquei entre
aspas, porque você vai digitar no terminal e precisa ser em string.
Depois de teclar
enter, o
django vai dizer que:
"É impossível adicionar o campo 'timestamp' com '
auto_now_add=True' ao usuário sem fornecer um padrão. Isso é porque o banco de dados precisa de algo para preencher as linhas existentes."
Então você escolhe a opção 1, que vai cair em um prompt
[default: timezone.now] >>>
Aí é só digitar:
timezone.now()
Pronto, a
migration concluída.
Pelo menos por enquanto a gente pode deixar o modelo User assim, se a gente precisar colocar mais coisas, podemos criar uma classe Profile, para extender as coisas a mais que poderemos querer colocar no User.
É isso, até a próxima. ;)
Código final da aula:
Canais do Youtube
Dêem um joinha 👍 na página do Código Fluente no
Facebook.
Sigam o Código Fluente no Instagram e no TikTok.
Código Fluente no Pinterest.
Meus links de afiliados:
Nos vemos na próxima então, \o/ 😉 Bons Estudos!