Aula 13 – Loja Online – Django – Custom QuerySets

More videos
Views
   

Loja Virtual – Ecommerce – Django – Custom QuerySets

Consultas personalizadas para produtos em destaque e ativos

Vimos na aula passada, como fazer um Custom Model Managers (gestores de modelos personalizados).

O Manager é a interface que interage com o banco de dados

No Django, os Custom Managers são uma ótima maneira de organizar a lógica de consulta reutilizável.

Na documentação do Django é dito que há dois motivos pelos quais você pode personalizar um gerenciador de modelo:

  • Para adicionar métodos extras do Gerenciador
  • Modificar o QuerySet inicial que o Manager retorna.

Agora vamos customizar queryset.

Featured Custom QuerySets

Featured Custom QuerySets

Dois novos campos no modelo product

Vamos introduzir dois novos campos ao nosso modelo product.

Um será o featured, ele será do tipo booleano, e definirá se um produto tá em destaque ou não.

O outro será o active, também booleano, que definirá se o produto está ativo ou não.

Vamos criar dentro da classe ProductManager, que é nosso model custom manager, os métodos:

  • featured, que vai devolver os produtos em destaque, ou seja, com featured igual a true.
  • all que retorna todos os produtos ativo.
  • e também vamos sobrescrever o get_queryset.

E para poder realmente chamar um conjunto de queries (query set) e conectá-las com nossa própria query personalizada (Custom QuerySets), iremos criar a classe ProductQuerySet.

E dentro dela criaremos dois métodos:

  • O active que vai retornar os produtos ativos, isto é, com o campo active igual a true;
  • E o featured, que vai retornar os produtos ativos e em destaque, ou seja, que além do campo active está como true, o campo featured também está como true.

Dessa maneira, a gente consegue por exemplo, fazer a seguinte chamada:

queryset = Product.objects.all().featured()

Sem a Featured Custom QuerySets a chamada teria que ser:

self.get_queryset().filter(featured = True)

Sem a QuerySets personalizada, não conseguiríamos encadear nossa query.

A gente vai acrescentar os métodos featured e active na queryset padrão.

Em src/products/models.py, insira o que tá em laranja.


from django.db import models

#Custom queryset
class ProductQuerySet(models.query.QuerySet):
    def active(self):
        return self.filter(active = True)

    def featured(self):
        return self.filter(featured = True, active = True)

class ProductManager(models.Manager):
    
    def get_queryset(self):
        return ProductQuerySet(self.model, using = self._db)
    
    def all(self):
        return self.get_queryset().active()

    def featured(self):
        #return self.get_queryset().filter(featured = True)
        return self.get_queryset().featured()

    def get_by_id(self, id):
        qs = self.get_queryset().filter(id = id)
        if qs.count() == 1:
            return qs.first()
        return None

# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    description = models.TextField()
    price       = models.DecimalField(decimal_places=2, max_digits=20, default=100.00)
    image       = models.FileField(upload_to = 'products/', null = True, blank = True)
    featured    = models.BooleanField(default = False)
    active      = models.BooleanField(default = True)


    objects = ProductManager()
    
    #python 3
    def __str__(self):
        return self.title
    #python 2
    def __unicode__(self):
        return self.title

Migrações

Como acrescentamos o campo featured ao nosso modelo, é necessário fazer as migrações para o banco.

Para isso rode:


python manage.py makemigrations
python manage.py migrate

Teremos uma view que lida apenas com o featured.

Abra o src/products/views.py e insira o que tá em laranja.


from django.http import Http404

from django.views.generic import ListView, DetailView
from django.shortcuts import render, get_object_or_404

from .models import Product

class ProductFeaturedListView(ListView):
    template_name = "products/list.html"
    
    def get_queryset(self, *args, **kwargs):
        return Product.objects.featured()

class ProductFeaturedDetailView(DetailView):
    queryset = Product.objects.all().featured()
    template_name = "products/featured-detail.html"

    #def get_queryset(self, *args, **kwargs):
        #request = self.request
        #return Product.objects.featured()

#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)

#Class Based View
class ProductDetailView(DetailView):
    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

    def get_object(self, *args, **kwargs):
        pk = self.kwargs.get('pk')
        instance = Product.objects.get_by_id(pk)
        if instance is None:
            raise Http404("Esse produto não existe!")
        return instance

#Function Based View
def product_detail_view(request, pk = None, *args, **kwargs):
    instance = Product.objects.get_by_id(pk)
    print(instance)
    if instance is None:
        raise Http404("Esse produto não existe!")

    context = {
        'object': instance
    }
return render(request, "products/detail.html", context)

Note que a ProductFeaturedListView é muito parecida com a ProductListView, assim como a ProductFeaturedDetailView também é bem parecida com a ProductDetailView.

Utilizamos Product.objects.featured() ao invés de Product.objects.all(), porque temos nosso método featured na classe ProductManager, que é nosso model custom manager.

O método featured faz o filtro devolvendo todos os products ativos e com featured setado como true.

Ele é a nossa query personalizada.

Criamos duas novas views, a ProductFeaturedListView e a ProductFeaturedDetailView.

Precisamos configurar as urls delas.

Abra o arquivo src/e_commerce/urls.py e faça as alterações abaixo:


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,
                            ProductFeaturedListView,
                            ProductFeaturedDetailView)

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('featured/', ProductFeaturedListView.as_view()),
        path('featured/<int:pk>/', ProductFeaturedDetailView.as_view()),
        path('products/', ProductListView.as_view()),
        path('products-fbv/', product_list_view), 
        path('products/', ProductDetailView.as_view()),
        path('products-fbv/', 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)

Não podemos esquecer do template featured-detail.html, então, crie ele dentro da pasta src/products/templates/product/ e coloque:

{{ object.title }} 
{{ object.description }} 
{% if object.image %}
    <img src='{{ object.image.url }}' class='img-fluid'/>
{% endif %}

Vamos fazer a mesma coisa que fizemos na tag img no featured-detail.html no /products/templates/products/detail.html


{{ object.title }} 
{{ object.description }} 
{% if object.image %}
    <img src='{{ object.image.url }}' class='img-fluid'/>
{% endif %}

Na próxima aula veremos SlugField.

Um slug é um rótulo curto para algo, contendo apenas letras, números, sublinhados ou hifens.

Eles geralmente são usados em URLs.

É isso!

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/featured_custom_querySets

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>