Aula 85 - Transformando as Views: Atualizando Registro, Login e Logout
Nesta aula, continuaremos nossa jornada transformando nossas
Functions Based Views em
Classes Based Views.
Atualizaremos as
Views de
registro,
login e
logout para seguir o padrão de
Views baseadas em
classe.
Para isso, vamos atualizar o
django_ecommerce/e_commerce/accounts/views.py.
A parte em
laranja é a
View como tava, usando
Function Based View, por isso está
comentada.
Agora vamos usar
Class Based View nas
Views do
Register,
Login e
Logout.
Atualizando a View de Registro (RegisterView)
Começamos transformando a
View de registro.
Substituímos a
função register_page pela
classe RegisterView, utilizando a classe
CreateView do
Django.
Atualizando a View de Login (LoginView)
Em seguida, transformamos a
View de
login.
Usamos a classe
FormView para criar a classe
LoginView, implementando o método
form_valid.
Atualizando a View de Logout (LogoutView)
Por fim, transformamos a
View de
logout.
Utilizamos a classe
View para criar a classe
LogoutView, que realiza o logout e renderiza o template.
Com essa transformação, nossas
Views estão mais organizadas e seguindo o padrão de
Classes Based Views do
Django.
Essa mudança facilita a manutenção e o desenvolvimento futuro do nosso projeto.
django_ecommerce/e_commerce/accounts/views.py
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.views.generic import CreateView, FormView, View
from django.http import HttpResponse,
from django.shortcuts import render,redirect
from django.utils.http import url_has_allowed_host_and_scheme
from .forms import LoginForm, RegisterForm, GuestForm
from .models import GuestEmail
def guest_register_view(request):
form = GuestForm(request.POST or None)
context = {
"form": form
}
next_ = request.GET.get('next')
next_post = request.POST.get('next')
redirect_path = next_ or next_post or None
if form.is_valid():
email = form.cleaned_data.get("email")
new_guest_email = GuestEmail.objects.create(email=email)
request.session['guest_email_id'] = new_guest_email.id
if url_has_allowed_host_and_scheme(redirect_path, request.get_host()):
return redirect(redirect_path)
else:
return redirect("/register/")
return redirect("/register/")
class LoginView(FormView):
form_class = LoginForm
success_url = '/' # Redireciona para a raiz do projeto
template_name = 'accounts/login.html'
def form_valid(self, form):
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(request=self.request, username=email, password=password)
if user is not None:
login(self.request, user)
try:
del self.request.session['guest_email_id']
except:
pass
return super(LoginView, self).form_valid(form)
#def login_page(request):
# form = LoginForm(request.POST or None)
# context = {
# "form": form
# }
# next_ = request.GET.get('next')
# next_post = request.POST.get('next')
# redirect_path = next_ or next_post or None
# if form.is_valid():
# username = form.cleaned_data.get("username")
# password = form.cleaned_data.get("password")
# user = authenticate(request, username=username, password=password)
# if user is not None:
# login(request, user)
# try:
# del request.session['guest_email_id']
# except:
# pass
# if url_has_allowed_host_and_scheme( redirect_path, request.get_host() ):
# return redirect( redirect_path )
# else:
# # Redireciona para uma página de sucesso.
# return redirect("/")
# else:
# #Retorna uma mensagem de erro de 'invalid login'.
# print("Login inválido")
# return render(request, "accounts/login.html", context)
class LogoutView(View):
template_name = 'accounts/logout.html'
def get(self, request, *args, **kwargs):
context = {
"content": "Você efetuou o logout com sucesso! :)"
}
logout(request)
return render(request, self.template_name, context)
#def logout_page(request):
# context = {
# "content": "Você efetuou o logout com sucesso! :)"
# }
# logout(request)
# return render(request, "accounts/logout.html", context)
class RegisterView(CreateView):
form_class = RegisterForm
template_name = 'accounts/register.html'
success_url = '/login/'
#User = get_user_model()
#def register_page(request):
# form = RegisterForm(request.POST or None)
# context = {
# "form": form
# }
# if form.is_valid():
# form.save()
# return render(request, "accounts/register.html", context)
Faça as alterações em azul no urls.py.
As mudanças realizadas no arquivo
urls.py visam atualizar as
URLs para utilizar as
Classes Based Views que foram criadas nas aulas anteriores.
Explicação das mudanças
Importações de Views
from accounts.views LoginView, RegisterView, LogoutView, guest_register_view
Foram adicionadas importações para as novas
Classes Based Views LoginView,
RegisterView e
LogoutView que foram definidas anteriormente.
Substituição das
URLs das
Functions Based Views pelas
Classes Based Views:
path('login/', LoginView.as_view(), name='login'),
path('register/', RegisterView.as_view(), name='register'),
path('logout/', LogoutView.as_view(), name='logout'),
As
URLs que anteriormente eram mapeadas para as functions Based Views
login_page,
register_page e
logout_page e foram atualizadas para utilizar as
Classes Based Views correspondentes:
LoginView.as_view(),
RegisterView.as_view() e
LogoutView.as_view().
Mantendo a Consistência
Ao substituir as
URLs das
Functions Based Views pelas
Classes Based Views, a estrutura do código fica mais consistente e segue o padrão de nomenclatura do Django para
Classes Based Views.
Isso torna o código mais organizado e facilita a manutenção e entendimento do projeto.
Com essas mudanças, o arquivo
urls.py foi atualizado para utilizar as
Classes Based Views no
LoginView,
RegisterView e
LogoutView em vez das
Functions Based Views originais.
Isso melhora a estrutura do código e segue as práticas recomendadas pelo
Django para o desenvolvimento de
Views.
django_ecommerce/e_commerce/e_commerce/urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.auth.views import LogoutView
from django.urls import path, include
from django.views.generic import TemplateView
from carts.views import cart_home, cart_detail_api_view
from accounts.views import LoginView, RegisterView, LogoutView, guest_register_view
from addresses.views import checkout_address_create_view, checkout_address_reuse_view
from .views import (home_page,
about_page,
contact_page
)
urlpatterns = [
path('', home_page, name='home'),
path('about/', about_page, name='about'),
path('contact/', contact_page, name='contact'),
path('cart/', include("carts.urls", namespace="cart")),
path('checkout/address/create/', checkout_address_create_view, name='checkout_address_create'),
path('checkout/address/reuse/', checkout_address_reuse_view, name='checkout_address_reuse'),
path('api/cart/', cart_detail_api_view, name='api-cart'),
path('login/', LoginView.as_view(), name='login'),
path('register/guest/', guest_register_view, name='guest_register'),
path('logout/', LogoutView.as_view(), name='logout'),
path('register/', RegisterView.as_view(), name='register'),
path('bootstrap/', TemplateView.as_view(template_name='bootstrap/example.html')),
path('search/', include("search.urls", namespace="search")),
path('products/', include("products.urls", namespace="products")),
path('admin/', admin.site.urls),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Comente a linha: user.active = False # send confirmation email
Troque o username para email (a parte azul no código abaixo)
django_ecommerce/e_commerce/accounts/forms.py
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import ReadOnlyPasswordHashField
User = get_user_model()
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password = forms.CharField(widget=forms.PasswordInput)
password_2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email']
def clean(self):
'''
Verify both passwords match.
'''
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_2 = cleaned_data.get("password_2")
if password is not None and password != password_2:
self.add_error("password_2", "Your passwords must match")
return cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ['full_name', 'email', 'password', 'active', 'admin']
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class GuestForm(forms.Form):
email = forms.EmailField()
class LoginForm(forms.Form):
email = forms.EmailField(label='Email')
password = forms.CharField(widget=forms.PasswordInput)
class RegisterForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password = forms.CharField(widget=forms.PasswordInput)
password_2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email']
def clean(self):
'''
Verify both passwords match.
'''
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_2 = cleaned_data.get("password_2")
if password is not None and password != password_2:
self.add_error("password_2", "Your passwords must match")
return cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password"])
# user.active = False # send confirmation email
if commit:
user.save()
return 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!