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)

Class Based Views e Function Based Views

Listando os produtos para o usuário comum

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

127.0.0.1:8000/products/

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. 😉

 

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>