Aula 08 – Loja Virtual – Ecommerce – Django – List View – CBVs – FBVs
Aula 08 – Loja Virtual – Ecommerce – Django – List View – CBVs – FBVs
Loja Virtual – Ecommerce – Django – Listar produtos
Agora vamos construir a list view dos produtos para o usuário comum.
CBVs (Class Based Views) versus FBVs (Function Based Views)
Voltar para página principal do blog
Todas as aulas desse curso
Aula 07 Aula 09
Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/list_view/e_commerce
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
Listando os produtos para o usuário comum.
Abra src/products/views.py
Primeiro importaremos generic views com:
from django.views.generic import ListView
Importaremos também o modelo produto com:
from .models import Product
Iremos criar a view primeiro utilizando CBVs (Class Based Views) e depois FBVs (Function Based Views) e vê a diferença entre elas.
src/products/views.py
from django.views.generic import ListView
from django.shortcuts import render
from .models import Product
class ProductListView(ListView):
#traz todos os produtos do banco de dados sem filtrar nada
queryset = Product.objects.all()
Agora vamos criar a FBVs (Function Based Views).
Obs. Não é necessário as duas formas, CBV e FBV. No código foi colocado os dois tipos apenas para ilustrar a diferença entre as duas formas de fazer uma view.
src/products/views.py
from django.views.generic import ListView
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()
#Function Based View
def product_list_view(request):
queryset = Product.objects.all()
context = {
'qs': queryset
}
return render(request, "products/list.html", context)
Já criamos a view com dois tipos diferentes de implementação: CBV e FBV, agora vamos adicioná-las as nossas URLs.
Abra src/e_commerce/urls.py e insira as linhas que estão em laranja.
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
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('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)
Suba o servidor se já não estiver rodando:
python manage.py runserver
Acesse 127.0.0.1:8000/products/
Veja que o django tá reclamando que não existe o template html, então vamos criá-lo.
Crie então src/products/templates/products/list.html e coloque:
{{ qs }}
Observe que a FBV conhece o context, já a CBV não, então, o que fizemos anteriormente só vai funcionar para a FBV, porque ela consegue enxergar a variável de contexto {{ qs }}
Faltou informar o nome do template na CBV, então, acrescente o que tá em laranja em src/products/views.py
from django.views.generic import ListView
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"
#Function Based View
def product_list_view(request):
queryset = Product.objects.all()
context = {
'qs': queryset
}
return render(request, "products/list.html", context)
Já criamos a view com dois tipos diferentes de implement
Com o servidor rodando, acesse: 127.0.0.1:8000/products-fbv/
O resultado deve ser algo como:
<QuerySet[<Product: Camiseta>, <Product: Tênis>]>
Já no caso da CBV não vai funcionar, porque ela não conhece o context.
Por isso vamos modificar a CBV.
src/products/views.py
from django.views.generic import ListView 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, *args, **kwargs): 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 = { 'qs': queryset } return render(request, "products/list.html", context)
A super é um atalho para chamar a classe base, que é a generic ListView, que vai como argumento da classe filha, a que a gente criou: ProductListView.
Ela recebe o nome da sub classe ProductListView como parâmetro e o self, que é a instância da própria classe.
Depois a chamada do método get_context_data() para pegar o contexto, passando *args e **kargs como parâmetros.
Toda CBV tem esse método, e o que esse método faz é pegar o context para qualquer query set ou qualquer coisa que a view fizer.
Mas, o que é *args e **kargs?
No *args e **kwargs, o asterísco ( * ) é um operador que transforma listas / dicionários em argumentos de uma função.
Vamos imaginar que você queira usar a função replace em uma string.
Essa função recebe 2 argumentos, o primeiro para o valor que será substituído e o segundo que é o novo valor.
'a menino'.replace('a', 'o')
‘o menino’
Agora tentando passar os parâmetros em uma lista:
args = ['a','o']
'a menino'.replace(args)
Erro Lançado:
Traceback (most recent call last): File “<stdin>”, line 1, in <module> TypeError: replace() takes at least 2 arguments (1 given)
Para que isso funcionar é só usar o operador *
'a menino'.replace(*args)
Saída:
‘o menino’
O ** é um operador que transforma um dicionário em keyword arguments de uma função.
Vamos a um exemplo, criaremos uma função que recebe dois argumentos, nome e idade:
d = {'nome' : 'Toti', 'idade': 50}
def my_two_args(nome, idade):
print(nome, idade)
my_two_args(d)
Saída:
Traceback (most recent call last): File “<stdin>”, line 1, in <module> TypeError: my_two_args() takes exactly 2 arguments (1 given)
Corrigindo:
d = {'nome' : 'Antonio', 'idade': 50}
def my_two_args(nome, idade):
print(nome, idade)
my_two_args(**d)
Saída:
Antonio 50
Como o context pode ter vários argumentos, então podemos ter:
def get_context_data(‘olá’, 312, [item1, item2, item3], outro=’olá’, num=312)
Não precisamos escrever explicitamente os argumentos, basta usar *arg e **kargs.
Precisamos de uma forma de pegar o context ou ver o que o context é na generic view, então acesse a generic view no browser em 127.0.0.1:8000/products/ e veja no console um dicionário onde é mostrado mais ou menos o seguinte:
{‘paginator’: None, ‘page_object’: None, ‘is_paginated’: False, ‘object_list’: <QuerySet[<Product: Camiseta>, <Product: Tênis>]>, ‘view’: <products.views.ProductListView object at 0x01034f935a7>}
Note que no browser, não aparece nada.
Faça um teste, coloque no src/products/template/products/list.html o seguinte:
{{ qs}}
{{ paginator }}
{{ is_paginated }}
{{ object_list }}
Veja o resultado no browser
O que nos interessa é o object_list, então apague todo o resto e deixe apenas o object_list:
src/products/template/products/list.html
{{ object_list }}
Em src/products/views.py comente o método get_context_data e em product_list_view troque o nome qs para object_list
from django.views.generic import ListView
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, *args, **kwargs):
#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)
Acesse novamento o browser em 127.0.0.1:8000/products e também 127.0.0.1:8000/products-fbv/
Veja que as duas implementações estão funcionando.
Vamos fazer uma modificação no src/products/template/products/list.html
{% for obj in object_list %}
{{ obj.title }} <br/>
{% endfor%}
Veja que agora tá listando nossos produtos nas duas implementações, CBV e FBV.
Na próxima aula, iremos atacar a Detail View, ou seja, o produto individualmente.
Aula 07 Aula 09
Todas as aulas desse curso
Voltar para página principal do blog
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/e_commerce
Obrigado, até a próxima e bons estudos. 😉