SHADI HILLES
SHADI HILLES

Reputation: 11

Django - Can't display category and sub category in template html

How can display category and sub category in product template? what is missing in below code

This is a part of View.py according product view, shows filtering category and subcategory from model.py.

class ProductView(View):
    def get(self,request,*args,**kwargs):
        categories=Categories.objects.filter(is_active=1)
        categories_list=[]
        for category in categories:
            sub_category=SubCategories.objects.filter(is_active=1,category_id=category.id)
            categories_list.append({"category":category,"sub_category":sub_category})

        merchant_users=MerchantUser.objects.filter(auth_user_id__is_active=True)
        return render(request,"admin_templates/product_create.html",{"categories":categories_list,"merchant_users":merchant_users})

this is part of model.py according model after migrate,

class Products(models.Model):
    id=models.AutoField(primary_key=True)
    url_slug=models.CharField(max_length=255)
    subcategories_id=models.ForeignKey(SubCategories,on_delete=models.CASCADE)
    product_name=models.CharField(max_length=255)
    brand=models.CharField(max_length=255, default="")
    product_max_price=models.CharField(max_length=255)
    product_discount_price=models.CharField(max_length=255)
    product_description=models.TextField()

productTemplate.html

<div class="col-lg-6">
    <label>Category</label>
    <select name="sub_category" class="form-control">
        {% for category in categories %}
            <optgroup  label={{ category.category.title }}>
            {% for sub_cat in category.sub_category %}
                <option value="{{ sub_cat.id }}">{{ sub_cat.title }}</option>
            {% endfor %}
              </optgroup>
        {% endfor %}
    </select>
</div>

Upvotes: 0

Views: 624

Answers (1)

Boaventura
Boaventura

Reputation: 1409

I implemented this solution and I will teach you step by step how to implement it. Rather, a spoiler of what we will learn:

enter image description here

With that in mind, let's get our hands dirty:

The first thing we will need to do is return the published categories to our template . In the file views.pyin the method of receita, where we return the receita.htmlchosen recipe to the template , which is also the page that displays the categories select, we will create a filter to return the published categories to us. And we can do this with the following code:

categorias = Receita.objects.filter(publicada=True).values('categoria').distinct('categoria')

See, through the Recipes object we filter all the recipes that have the true flag for published. After that, we just get the category values. So we say to django: - django, returns me only the recipes that have true for published, but I just want the category column . And the distinct? To serve? The distinct will guarantee us that there will be no repetition in the data. Example:

If the filter returns to us that the category column has: dessert, salty, dessert, soup, salty ... what the distinct will do is to avoid repeated data, with that we will only have: dessert, salty, soup. How are you? In possession of that, we need to pass this value to our dictionary that will go to the context of our template:

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

Note that we pass to the 'categories' key the value of our filter that was saved in the categories variable.

Now we can move the dictionary into context:

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

Great, now we can access the categories in our template receita.html'

And to display them we can go through each category and put the name of that category in our select. Also remembering that we need to redirect the url to our search route when we click on the search button:

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

Now, with our template ready, you will be able to see the categories in the select.

The next step is to modify our search method so that it can search by category and not just the name of the recipe as it used to.

In views.py, in the method of buscar, let's say to django: search for the name of the recipe or all the recipes in that category. We can do this through the object Q used to set up queries where we will have more than one possible answer :

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

That is, filter the recipes that have that name or that have that category. And in order to Qwork, we will need to import it:

from django.db.models import Q

You can test it! With these modifications you will be able to use the select categories.


Summary of modified files:

views.py file

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)

. Recipe.html file .

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

Some django documentation references:

Distinc

Object Q

I hope I helped you

Upvotes: 1

Related Questions