Aula 35 – Loja Online – Django – Melhorando o search com Q Lookups

Aula 35 – Loja Online – Django – Melhorando o search com Q Lookups

Melhorando o search com Q Lookups

Melhorando o search com Q Lookups

Voltar para página principal do blog

Todas as aulas desse curso

Aula 34               Aula 36

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no GITHUB.

Ah, se puder, clica na estrela nos meus repositórios pra dá uma força ao meu perfil no GITHUB

Código final da aula:

https://github.com/toticavalcanti/django_ecommerce/tree/q_lookups

Recapitulando

Na aula passada criamos um formulário de pesquisa isolado para poder reutilizar o código.

Usamos o método de GET passando a URL, nesse caso o /search, a ser tratada pela src/search/view.py.

Melhorando o search com Q Lookups

Nossa busca só funciona pelo título, não pesquisa por outros campos.

Vamos utilizar Q que iremos importar do django.db.models, ele nos ajudará a compor querysets.

Vamos ao código.

src/search/views.py


from django.db.models import Q
from django.shortcuts import render
from django.views.generic import ListView
from products.models import Product

class SearchProductView(ListView):
    template_name = "search/view.html"

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        query = self.request.GET.get('q')
        context['query'] = query
        #SearchQuery.objects.create(query=query)
        return context

    def get_queryset(self, *args, **kargs):
        request = self.request
        print('Solicitação', request)
        result = request.GET
        print('Resultado: ', result)
        query = result.get('q',  None) # method['q']
        print('Consulta', query)
        if query is not None:
            lookups = Q(title__contains = query) | Q(description__contains = query)
            return Product.objects.filter(lookups).distinct()
        return Product.objects.featured()

O distinct é para não repetir um mesmo produto, já que um mesmo produto pode se encaixar nas duas queries.

Refatorando

Vamos transferir essa responsabilidade de devolver os itens correspondentes a pesquisa do usuário, para o modelo.

Vamos mover o conteúdo em azul no código acima para o src/products/models.py.

src/products/models.py


from django.db.models import Q
from django.db import models
from .utils import unique_slug_generator
from django.db.models.signals import pre_save
from django.urls import reverse

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

    def search(self, query):
        lookups = Q(title__contains = query) | Q(description__contains = query)
        return self.filter(lookups).distinct()

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

    def search(self, query):
        return self.get_queryset().active().search(query)

# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    slug        = models.SlugField(blank = True, unique = True)
    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)
    timestamp   = models.DateTimeField(auto_now_add = True)


    objects = ProductManager()

    def get_absolute_url(self):
        #return "/products/{slug}/".format(slug = self.slug)
        return reverse("products:detail", kwargs={"slug": self.slug})
    
    #python 3
    def __str__(self):
        return self.title
        
    #python 2
    def __unicode__(self):
        return self.title

def product_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(instance)

pre_save.connect(product_pre_save_receiver, sender = Product)

src/search/views.py


from django.shortcuts import render
from django.views.generic import ListView
from products.models import Product

class SearchProductView(ListView):
    template_name = "search/view.html"

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        query = self.request.GET.get('q')
        context['query'] = query
        #SearchQuery.objects.create(query=query)
        return context

    def get_queryset(self, *args, **kargs):
        request = self.request
        print('Solicitação', request)
        result = request.GET
        print('Resultado: ', result)
        query = result.get('q',  None) # method['q']
        print('Consulta', query)
        if query is not None:
            return Product.objects.search(query)
        return Product.objects.featured()

Vamos acrescentar o preço também.

src/products/models.py


from django.db.models import Q
from django.db import models
from .utils import unique_slug_generator
from django.db.models.signals import pre_save
from django.urls import reverse

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

    def search(self, query):
        lookups = (Q(title__contains = query) | 
                   Q(description__contains = query) | 
                   Q(price__contains = query))
        return self.filter(lookups).distinct()

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

    def search(self, query):
        return self.get_queryset().active().search(query)

# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    slug        = models.SlugField(blank = True, unique = True)
    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)
    timestamp   = models.DateTimeField(auto_now_add = True)


    objects = ProductManager()

    def get_absolute_url(self):
        #return "/products/{slug}/".format(slug = self.slug)
        return reverse("products:detail", kwargs={"slug": self.slug})
    
    #python 3
    def __str__(self):
        return self.title
        
    #python 2
    def __unicode__(self):
        return self.title

def product_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(instance)

pre_save.connect(product_pre_save_receiver, sender = Product)

Com o servidor rodando acesse:

http://127.0.0.1:8000/search

E teste.

É isso pessoal, nos vemos na próxima!

Aula 34                      Aula 36

Todas as aulas desse curso

Voltar para página principal do blog

Código final da aula:

https://github.com/toticavalcanti/django_ecommerce/tree/q_lookups

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Link do código fluente no Pinterest

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

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>