Aula 81 – Loja Online – Gerenciador do Modelo User
Aula 81 – Loja Online – Gerenciador do Modelo User
Voltar para página principal do blog
Todas as aulas desse curso
Aula 80 Aula 82
Redes Sociais:
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
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.