Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Filtrando por categoria

Vai haver alguma aula relativo a busca por categoria, visto que tinha um menu de opcoes (massa, comida brasileira, vegana) mas nao foi apresentado nada

3 respostas
solução!

Oi Clecio, tudo bem com você?

Nos cursos de django que há atualmente na plataforma, a busca por categoria não é ensinada. Mas, implementei essa solução e vou te ensinar passo a passo como implementá-la. Antes, um spoiler do que iremos aprender:

categoria

Visto isso, vamos colocar a mão na massa:

  • A primeira coisa que precisaremos fazer é retornar as categorias publicadas para o nosso template. No arquivo views.py no método de receita, onde retornamos para o template receita.html a receita escolhida, que também é a página que exibe o select de categorias, vamos criar um filtro para nos retornar as categorias publicadas. E podemos fazer isso com o seguinte código:
categorias = Receita.objects.filter(publicada=True).values('categoria').distinct('categoria')

Veja, através do objeto de Receitas filtramos todas as receitas que possuem a flag verdadeira para publicada. Após isso, pegamos apenas os valores de categoria. Então dizemos para o django: - django, me retorna apenas as receitas que possuem verdadeiro para publicada, mas eu quero apenas a coluna de categoria. E o distinct? Para serve? O distinct irá nos garantir que não haverá repetição nos dados. Exemplo:

  • Se o filter nos retornar que a coluna categoria possui: sobremesa, salgado, sobremesa, sopa, salgado... o que o distinct fará é evitar dados repetidos, com isso teremos apenas: sobremesa, salgado, sopa. Tudo bem?

De posse disso, precisamos passar esse valor para o nosso dicionário que irá para o contexto do nosso template:

receita_a_exibir = {
        'receita': receita,
        'categorias': categorias
    }

Observe que passamos para chave 'categorias' o valor do nosso filtro que foi salvo na variável categorias .

Agora podemos passar o dicionário para o contexto:

return render(request, 'receita.html', receita_a_exibir)

Ótimo, agora já conseguimos acessar as categorias no nosso template receita.html'

E para exibi-las podemos percorrer cada categoria e colocarmos em nosso select o nome dessa categoria. Lembrando também que precisamos redirecionar a url para nossa rota de buscar quando clicarmos no botão de busca:

<div class="receipe-post-search mb-80">
    <div class="container">
        <form action="{% url 'buscar' %}">
            <div class="row">
                <div class="col-12 col-lg-5">
                   <select type="text" name="buscar">
                   {% for categoria in categorias %}
                        <option value="{{categoria.categoria}}">{{categoria.categoria}}</option>
                    {% endfor %}
                    </select> 
                </div>
                <div class="col-12 col-lg-2 text-right">
                    <button type="submit" class="btn delicious-btn">Buscar</button>
                </div>
            </div>
        </form>
    </div>
</div>

Agora, com o nosso template pronto, você já conseguirá ver as categorias no select.

O próximo passo é modificar o nosso método de busca para que ele possa buscar pela categoria e não somente pelo nome da receita como ocorria.

Em views.py, no método de buscar, vamos dizer ao django: busque pelo nome da receita ou todas as receitas daquela categoria. Podemos fazer isso através do objeto Q que serve para montar consultas onde teremos mais de uma possibilidade de resposta:

lista_receitas = lista_receitas.filter(Q(nome_receita__icontains=nome_a_buscar) | Q(categoria__icontains=nome_a_buscar))

Ou seja, filtre as receitas que possuem aquele nome ou que possuem aquela categoria. E para o Q funcionar, precisaremos importá-lo:

from django.db.models import Q

Pode testar! Com essas modificações você conseguirá utilizar o select de categorias.

Resumo dos arquivos modificados:

  • Arquivo views.py
from django.db.models import Q
def buscar(request):
    lista_receitas = Receita.objects.filter(publicada=True).order_by('-data_receita')

    if 'buscar' in request.GET:
        nome_a_buscar = request.GET['buscar']
        if buscar:
            lista_receitas = lista_receitas.filter(Q(nome_receita__icontains=nome_a_buscar) | Q(categoria__icontains=nome_a_buscar))

    dados = {
        'receitas' : lista_receitas,
    }

    return render(request, 'buscar.html', dados)
def receita(request, receita_id):
    receita = get_object_or_404(Receita, pk=receita_id)
    categorias = Receita.objects.filter(publicada=True).values('categoria').distinct('categoria')

    receita_a_exibir = {
        'receita': receita,
        'categorias': categorias
    }
    return render(request, 'receita.html', receita_a_exibir)

Arquivo receita.html

<div class="receipe-post-search mb-80">
    <div class="container">
        <form action="{% url 'buscar' %}">
            <div class="row">
                <div class="col-12 col-lg-5">
                   <select type="text" name="buscar">
                   {% for categoria in categorias %}
                        <option value="{{categoria.categoria}}">{{categoria.categoria}}</option>
                    {% endfor %}
                    </select> 
                </div>
                <div class="col-12 col-lg-2 text-right">
                    <button type="submit" class="btn delicious-btn">Buscar</button>
                </div>
            </div>
        </form>
    </div>
</div>

Algumas referências da documentação do django:

Clecio, espero ter te ajudado. Se houver algum problema na execução ou caso tenha ficado obscuro alguma parte, não se acanhe. Estou à disposição. Abraços e bons estudos :D

Muito obrigado. Vlw