Aula 81 – Loja Online – Gerenciador do Modelo User

Aula 81 – Loja Online – Gerenciador do Modelo User

Loja Online - Django

Loja Online – Django

Pacote Programador Fullstack

Pacote Programador Fullstack

Voltar para página principal do blog

Todas as aulas desse curso

Aula 80                       Aula 82

Redes Sociais:

facebook

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Quer aprender python3 de graça e com certificado? Acesse então:

https://workover.com.br/python-codigo-fluente

Canais do YoutubeRemover imagem destacada

Toti

Lofi Music Zone Beats

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


 

Aula 81 – Loja Online – Gerenciador do Modelo User

Como vimos na aula 79, o modelo de usuário padrão é definido no módulo django.contrib.auth.models e inclui campos comuns como nome de usuário, email e senha.

Além do modelo de usuário, o Django também inclui um gerenciador de modelo de usuário padrão, que é responsável por criar, atualizar, excluir e pesquisar objetos de usuário no banco de dados.

O gerenciador de modelo de usuário padrão é definido no modelo de usuário padrão do Django e é acessível por meio do objeto User.objects em seus pontos de código.

No entanto, se você criar seu próprio modelo de usuário personalizado, precisará criar um gerenciador de modelo de usuário personalizado também, que será responsável por gerenciar objetos do seu modelo de usuário personalizado no banco de dados.

O gerenciador de modelo de usuário personalizado deve herdar da classe BaseUserManager do Django e substituir os métodos relevantes para criar, atualizar, excluir e pesquisar objetos do seu modelo de usuário personalizado.

Crie a branch para trabalhar no código da aula, no meu caso, vou chamar de user-model-manager.

git checkout -b user-model-manager

django_ecommerce/e_commerce/accounts/models.py


from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser, BaseUserManager
)

class UserManager(BaseUserManager):
    def get_by_natural_key(self, email):
        return self.get(email=email)
    def create_user(self, email, password = None, is_active = True, is_staff = False, is_admin = False):
        if not email:
            raise ValueError("O Usuário deve ter um endereço de email.")
        if not password:
            raise ValueError("O Usuário deve ter uma senha.")
        user_obj = self.model(
            email = self.normalize_email(email)
        )
        user_obj.set_password(password) # muda a senha
        user_obj.staff = is_staff
        user_obj.admin = is_admin
        user_obj.active = is_active
        user_obj.save(using=self._db)
        return user_obj
    def create_staffuser(self, email, password = None):
        user = self.create_user(
            email,
            password = password,
            staff = True
        )
        return user
    def create_superuser(self, email, password = None):
        user = self.create_user(
            email,
            password = password,
            is_staff = True,
            is_admin = True,
        )
        return user
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
    objects = UserManager()
    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

Faça a migrations com: python manage.py makemigrations

Provavelmente, será solicitado o timestamp, escolha a opção 1) Provide a one-off…, digitando 1.

No prompt python, que vai entrar automaticamente, digite: timezone.now e dê enter.

Agora as migrations foram efetivadas.

Faltou só o migrate: python manage.py migrate

django_ecommerce/e_commerce/e_commerce/settings.py


"""
Django settings for e_commerce project.
Generated by 'django-admin startproject' using Django 2.1.4.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'xjmv-0^l__duq4-xp54m94bsf02lx4&1xka_ykd_(7(5#9^1o^'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    #our apps
    'addresses',
    'billing',
    'accounts',
    'carts',
    'orders',
    'products',
    'search',
    'tags',
]

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

AUTH_USER_MODEL = 'accounts.User' # changes the built-in user model to ours
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

LOGOUT_REDIRECT_URL = '/login/'
ROOT_URLCONF = 'e_commerce.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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',
            ],
        },
    },
]

WSGI_APPLICATION = 'e_commerce.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
     os.path.join(BASE_DIR, "static_local")
]

STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_cdn", "static_root")

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_cdn", "media_root")

Rode o servidor: python manage.py runserver

Veja que no 127.0.0.1:8000/admin/login, agora mostra o email como a única opção de login.

Fizemos mudanças na estrutura do banco, na tabela de user que está ligada a billing.

Por isso, vamos ter que criar não só um novo superuser com:

python manage.py createsuperuser

Vai dá um erro de UNIQUE constraint failed, por causa do billing que está ligado ao id de um usuário.

Solução

Podemos deletar todos os billing profiles.

Mas, essa é uma boa oportunidade para destruir o banco todo, mas mantendo parte dele, no nosso caso, os produtos, porque o resto dos dados são mais fáceis e rápidos de serem criados.

O que vamos fazer então é o seguinte: para não ter que recadastrar os produtos que a gente já tem no banco, vamos salvar ele para depois recuperar ele no banco novo.

Para isso, vamos usar um recurso chamado fixture.

Na pasta do app products: django_ecommerce/e_commerce/products

Crie uma pasta chamada: fixtures

django_ecommerce/e_commerce/products/fixtures

Com o comando abaixo, criamos o arquivo products.json dentro da pasta fixtures.

python manage.py dumpdata --format json --indent 4 > products/fixtures/products.json

Podemos renomear o nosso banco sqlite: db.sqlite3 para db2.sqlite3.

Delete todas as migrations e o __pycache__, deixe so o __init__.py no app django_ecommerce/e_commerce/accounts/migrations.

Migrations

python manage.py makemigrations

Migrate

python manage.py migrate

Carregando os dados dos produtos

python manage.py loaddata products/fixtures/products.json

Criando o super user

python manage.py createsuperuser

Caso você esqueça da senha, para mudar ela use:

python manage.py changepassword <user_name>

Seguindo a criação do super user

Defina um email e senha.

Se tudo correu bem, dessa vez não houve problema na criação do super user.

Suba o servidor

python manage.py runserver

Faça o login com o email e senha que você cadastrou: 127.0.0.1:8000/admin/login

Provavelmente vai dá um erro quando fizer o login: ‘User’ object has no attribute ‘has_module_perms’

Esse é um método que o Custom User Model Django espera que se tenha implementado.

Para solucionar, vanos criar.

django_ecommerce/e_commerce/accounts/models.py


from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser, BaseUserManager
)

class UserManager(BaseUSerManager):
    def create_user(self, email, password = None, is_active = True, is_staff = False, is_admin = False):
        if not email:
            raise ValueError("O Usuário deve ter um endereço de email.")
         if not password:
            raise ValueError("O Usuário deve ter uma senha.")
        user_obj = self.model(
            email = self.normalize_email(email)
        )
        user_obj.set_password(password) # muda a senha
        user_obj.staff = is_staff
        user_obj.admin = is_admin
        user_obj.active = is_active
        user_obj.save(using=self._db)
        return user_obj
    def create_staffuser(self, email, password = None):
        user = self.create_user(
            email,
            password = password,
            staff = True
        )
        return user
    def create_superuser(self, email, password = None):
        user = self.create_user(
            email,
            password = password,
            is_staff = True,
            is_admin = True,
        )
        return user
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
    objects = UserManager()
    def __str__(self):
        return self.email
    def get_full_name(self):
        return self.email
    def get_short_name(self):
        return self.email
    def has_perms(self, perm, object=None):
        return True
    def has_module_perms(self, app_label):
        return True
    @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

Faça o login: 127.0.0.1:8000/admin/login

Veja que o User não aparece no admin, só o accounts.

Abra o django_ecommerce/e_commerce/accounts/admin.py

django_ecommerce/e_commerce/accounts/admin.py


from django.contrib import admin
from django.contrib.auth import get_user_model
from .models import GuestEmail
User = get_user_model()
admin.site.register(User)
admin.site.register(GuestEmail)
# Register your models here.

Salve, dê um refresh na página e veja que agora aparece o User no painel admin.

Na próxima aula vamos melhorar o formulários para nosso User personalizado.

É isso, até a próxima. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 80                       Aula 82

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!

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>