Home > Mobile >  How can I get and display ForeignKey data in a Django template
How can I get and display ForeignKey data in a Django template

Time:12-31

I'm attempting to only display cards based on their category_name.

for eg. I have 2 simple models, Product and Category:

class Category(models.Model):
    category_name = models.CharField(max_length=254, blank=False, null=False)
    url_name = models.SlugField(max_length=254, unique=True)
    category_image = models.ImageField(
        null=False, blank=False, default='', upload_to='category_images', help_text='This will be the category image')
    category_description = RichTextField(default='')

    class Meta:
        verbose_name = 'Categories'

    def __str__(self):
        return self.category_name

    def get_category_name(self):
        return self.category_name


class Product(models.Model):
    main_product_image = models.ImageField(
        null=False, blank=False, default='', upload_to='product_images', help_text='This will be the main image in the carousel.')
    alternative_image_1 = models.ImageField(
        null=True, blank=True, upload_to='product_images', help_text='This will be the first image in the carousel.')
    alternative_image_2 = models.ImageField(
        null=True, blank=True, upload_to='product_images', help_text='This will be the second image in the carousel.')
    category = models.ForeignKey(
        'Category', null=True, blank=True, help_text='Assign product to category', on_delete=models.CASCADE)
    created_by = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='product_creator', null=True)

    sku = models.CharField(max_length=254, null=True, blank=True)
    name = models.CharField(max_length=254)
    product_display_description = RichTextField(default='')
    spice_rating = models.CharField(max_length=1, null=True, blank=True)
    has_sizes = models.BooleanField(default=False, null=True, blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2, default='0')
    add_to_carousel = models.BooleanField(default=False)
    in_stock = models.BooleanField(default=True)
    is_active = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Products'
        ordering = ('-created',)

    def __str__(self):
        return self.name

I would like to then display these product cards on the frontend based on their category names.

Using something simple like this:

{% for product in products_processor|slice:':4' %}
{% if product.category.category_name == 'sauces' %}
<div ></div>
{% endif %}
{% endfor %}

views.py:

def all_products(request):
    """Shows and displays all products."""
    products = Product.objects.all()
    query = None
    categories = None
    sort = None
    direction = None

    if request.GET:

        # Handles sorting by price, rating etc...
        if 'sort' in request.GET:
            sortkey = request.GET['sort']
            sort = sortkey
            if sortkey == 'name':
                sortkey = 'lower_name'
                products = products.annotate(lower_name=Lower('name'))
            if sortkey == 'category':
                sortkey = 'category__name'
            if 'direction' in request.GET:
                direction = request.GET['direction']
                if direction == 'desc':
                    sortkey = f'-{sortkey}'
            products = products.order_by(sortkey)

        # Handles categories
        if 'category' in request.GET:
            categories = request.GET['category'].split(',')
            products = products.filter(category__url_name__in=categories)
            categories = Category.objects.filter(url_name__in=categories)

        # Handles Searches
        if 'q' in request.GET:
            query = request.GET['q']
            if not query:
                messages.error(request, 'Please enter a search query!')
                return redirect(reverse('products'))

            queries = Q(name__icontains=query) | Q(
                product_display_description__icontains=query)
            products = products.filter(queries)

    current_sorting = f'{sort}_{direction}'

    product_context = {
        'products': products,
        'search_term': query,
        'current_categories': categories,
        'current_sorting': current_sorting,
    }

    return render(request, 'products/products.html', product_context)


def product_detail(request, product_id):
    """Displays individual products."""
    product = get_object_or_404(Product, pk=product_id)

    product_context = {
        'product': product,
    }

    return render(request, 'products/product_detail.html', product_context)

This method doesn't seem to be working. If anyone can point me in the right direction that would be greatly appreciated.

CodePudding user response:

Based on what I see in your view. In your template you are doing {% for product in products_processor|slice:':4' %}, in which products_processor seems like it is supposed to be part of your context. The issue I see is that your context object from your view does not contain a products_processor, only a products. Maybe try replacing products_processor with products in your template.

  • Related