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. ;)

Voltar para página principal do blog

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

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:

Hostinger

Digital Ocean

One.com

Nos vemos na próxima então, \o/  😉 Bons Estudos!