Aula 09 – Loja Virtual – Ecommerce – Django – Detail View
Aula 09 – Loja Virtual – Ecommerce – Django – Detail View
Loja Virtual – Ecommerce – Django – Detalhes de cada produto
Agora vamos construir a página que vai mostrar os detalhes de cada produtos para o usuário comum.
Voltar para página principal do blog
Todas as aulas desse curso
Aula 08 Aula 10
Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/list_view
Curta a página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/
Vou deixar meu link de referidos na digitalocean pra vocês.
Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:
Digital Ocean
Esse outro link é da one.com:
One.com
Detail View
Será bem parecido com o list view que fizemos na aula passada. Vamos implementar as duas versões da detail view, como fizemos na product list view: Class Based View e Function Based View.
Não é necessário ter as duas versões, CBV e FBV, nesse tutorial estamos fazendo as duas versões apenas para mostrar a diferença entre as implementações.
Em src/products/views.py crie a CBV e FBV da detail view. O que tá em laranja é o que tá sendo alterado.
from django.views.generic import ListView, DetailView from django.shortcuts import render from .models import Product #Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/list.html"
#def get_context_data(self): #context = super(ProductListView, self).get_context_data(*args, **kwargs) #print(context) #return context
#Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self, *args, **kwargs): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_detail_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/detail.html", context)
Agora em src/e_commerce/urls.py importe a CBV e a FBV da detail view e adicione ao urlpatterns:
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path
from products.views import ProductListView, product_list_view, ProductDetailView, product_detail_view
from .views import home_page, about_page, contact_page, login_page, register_page
urlpatterns = [
path('', home_page),
path('about/', about_page),
path('contact/', contact_page),
path('login/', login_page),
path('register/', register_page),
path('products/', ProductListView.as_view()),
path('products-fbv/', product_list_view),
path('products/<int:pk>', ProductDetailView.as_view()),
path('products-fbv/<int:pk>', product_detail_view),
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)
Vamos dá uma olhada em como uma query funciona.
Com o servidor rodando acesse: 127.0.0.1:8000/products-fbv/2
Com esse request, tentamos acessar o produto com o id 2, através da Function Based View da detail view, isto é, os detalhes do produto com id 2.
Isso irá lançar uma mensagem de erro no browser, mais ou menos assim:
product_detail_view() got an unexpected keyword argument ‘pk’
Vamos colocar o *args e o **kwargs na product_detail_view e imprimir no console para ver o conteúdo que eles trazem.
src/products/views.py
from django.views.generic import ListView, DetailView from django.shortcuts import render from .models import Product #Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/list.html"
#def get_context_data(self): #context = super(ProductListView, self).get_context_data(*args, **kwargs) #print(context) #return context
#Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_detail_view(request, *args, **kwargs): print(args) print(kwargs) queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/detail.html", context)
Note que o erro já era, porque agora product_detail_view tá recebendo *kargs e **kwargs.
O resultado do print no console será algo como: () do args e {‘pk’: ‘2’} do kwargs.
Vamos adicionar pk = None nos argumentos da product_detail_view.
src/products/views.py
from django.views.generic import ListView, DetailView from django.shortcuts import render from .models import Product #Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/list.html"
#def get_context_data(self): #context = super(ProductListView, self).get_context_data(*args, **kwargs) #print(context) #return context
#Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_detail_view(request, pk = None, *args, **kwargs): print(args) print(kwargs) queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/detail.html", context)
Veja que o resultado do print args e kwargs agora estão vazios.
Cada objeto django por padrão tem uma chave primária, é o id do objeto.
Ela é criada automaticamente.
Sempre que criamos um objeto no django, ele cria um identificador para o objeto.
Vamos pegar o id do object com Product.objects.get().
src/products/views.py
from django.views.generic import ListView, DetailView from django.shortcuts import render from .models import Product
#Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self): #context = super(ProductListView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_detail_view(request, pk = None, *args, **kwargs): instance = Product.objects.get(pk = pk) #get the object id context = { 'object': instance } return render(request, "products/detail.html", context)
Com o servidor rodando acesse: 127.0.0.1:8000/products-fbv/4
Será lançada uma exceção dizendo:
product matching query does not exists (produto correspondente a consulta não existe)
Simplesmente porque esse object com id 4 não existe no banco.
Teste agora a CBV:
No product found matching the query (Nenhum produto encontrado correspondente à consulta)
Uma maneira de lidar com isso é usar o get_object_or_404, para isso vamos modificar o src/products/views.py
from django.views.generic import ListView, DetailView from django.shortcuts import render, get_object_or_404 from .models import Product #Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/list.html"
#def get_context_data(self): #context = super(ProductListView, self).get_context_data(*args, **kwargs) #print(context) #return context
#Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" #def get_context_data(self): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context #Function Based View def product_detail_view(request, pk = None, *args, **kwargs): #instance = Product.objects.get(pk = pk) #get the object id instance = get_object_or_404(Product, pk = pk) context = { 'object': instance } return render(request, "products/detail.html", context)
Com o servidor rodando acesse: 127.0.0.1:8000/products-fbv/4
Veja que a FBV agora não lança nenhuma exceção e sim o mesmo erro que a CBV.
No product found matching the query (Nenhum produto encontrado correspondente à consulta)
Agora vamos descomentar o método get_context_data na nossa classe ProductDetailView em src/products/views.py
from django.views.generic import ListView, DetailView from django.shortcuts import render, get_object_or_404 from .models import Product #Class Based View class ProductListView(ListView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/list.html"
#def get_context_data(self): #context = super(ProductDetailView, self).get_context_data(*args, **kwargs) #print(context) #return context
#Function Based View def product_list_view(request): queryset = Product.objects.all() context = { 'object_list': queryset } return render(request, "products/list.html", context) #Class Based View class ProductDetailView(DetailView): #traz todos os produtos do banco de dados sem filtrar nada queryset = Product.objects.all() template_name = "products/detail.html" def get_context_data(self): context = super(ProductDetailView, self).get_context_data(*args, **kwargs) print(context) return context #Function Based View def product_detail_view(request, pk = None, *args, **kwargs): #instance = Product.objects.get(pk = pk) #get the object id instance = get_object_or_404(Product, pk = pk) context = { 'object': instance } return render(request, "products/detail.html", context)
Acesse um produto que exista.
O produto com id 2 por exemplo, existe, no meu caso é o tênis:
Agora o browser irá mostrar: TemplateDoesNotExist at /products/2/, se você olhar no console, verá o resultado do print do contexto, algo como:
{‘object’: <Product: Tênis>, ‘product’: <Product: Tênis>, ‘view’: <products.views.ProductDetailView object at ….}
Vamos criar o template da detail view.
src/products/template/products/detail.html
{{ object.title }} <br/>
{{ object.description }} <br/>
Veja o resultado no browser
Valeu, até. \o/ 🙂
Voltar para página principal do blog
Todas as aulas desse curso
Aula 08 Aula 10
Curta a página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/
Vou deixar meu link de referidos na digitalocean pra vocês.
Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:
Digital Ocean
Esse outro link é da one.com:
One.com
Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/list_view
Obrigado, até a próxima e bons estudos. 😉
Primeiro de tudo, excelente trabalho o que você tem feito aqui meu amigo! Ótima didática e conteúdo!
Apenas para observação de todos que estiverem acompanhando por aqui, na última atualização da view de products (descomentar o get_context_data) estão faltando 2 parâmetros na chamada: *args e **kwargs, causando erro de object não esperado na função. Devereia ser assim:
def get_context_data(self, *args, **kwargs):
context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
print(context)
return context
Olá Rodrigo, blz?
Acabei de ver no post dessa aula e também na branch detail_view no GitHub, que é a branch dessa aula e o código tá exatamente como você colocou aí, tá assim, tanto na branch detail_view como no post da aula 09:
Exatamente igual ao que você colocou como o que deveria ser, com o .get_context_data(*args, **kwargs) .
Enfim, de qualquer forma valeu. 😉