Django two models with many-to-many relation print on template - python

I have category and product models. These have a many-to-many relation.
My models
class ProductCategories(models.Model):
name = models.CharField(max_length = 60)
image = models.ImageField(upload_to = 'ProductCategories')
publish_date = models.DateTimeField(auto_now=False, auto_now_add=True)
is_available = models.BooleanField()
class Product(models.Model):
category = models.ManyToManyField(ProductCategories)
name = models.CharField(max_length = 60)
price = models.DecimalField(max_digits=65, decimal_places=2)
description = models.TextField()
options = models.TextField()
tags = models.TextField()
publish_date = models.DateTimeField(auto_now=False, auto_now_add=True)
stock_number = models.IntegerField()
is_available = models.BooleanField()
My view
def category(request):
categories = ProductCategories.objects.all()
products = Product.objects.none()
for category in categories:
products = products.union(Product.objects.filter(category = category)[:4])
return render(request, 'shop/shopping.html', {'categories' : categories, 'products' : products})
My Html
{% for category in categories %}
<div class="row">
<h3 style="padding-left: 15px; padding-bottom: 15px">{% filter upper %}{{ category.name }}{% endfilter %}</h3>
</div>
<div class="row">
{% for product in products %}
{{ product.category }}
{% endfor %}
</div>
{% endfor %}
I would like to list categories. Under each category, 4 products will be listed.
is it possible to pass queryset which includes both products and their categories?
Thanks,

You can simply do:
def category(request):
categories = ProductCategories.objects.all()
return render(request, 'shop/shopping.html', {'categories' : categories})
And the template
{% for category in categories %}
{% for product in category.product_set.all|slice:":4" %}
{{ product.name }}
{% endfor %}
{% endfor %}

Related

Using foreign key as object in Django Telmplates

I'm trying to build a structure using Django Rest Framework to show some data in my html templates. But I can't show data from a model with ForeignKey.
My structure should be like this:
{% for category in categories %}
{{ category.category }} #category is the variable name
{% for channel in category.channel_set.all %}
{{ channel.title }}
{{ endfor }}
{{ endfor }}
But I can't print the channel variables in html files.
models.py:
class Category(models.Model):
user = models.ForeignKey(
'auth.User',
on_delete=models.DO_NOTHING,
unique=False,
)
category = models.CharField(
max_length=255,
unique=True,
)
_id = models.ObjectIdField(auto_created=True, serialize=False)
event_creation = models.DateTimeField(auto_now=True)
event_updated = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'category'
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.category
class Channel(models.Model):
user = models.ForeignKey(
'auth.User',
on_delete=models.DO_NOTHING,
)
_id = models.ObjectIdField(auto_created=True, serialize=False)
date_creation = models.DateTimeField(auto_now=True)
date_updated = models.DateTimeField(auto_now=True)
category = models.ForeignKey(
Category,
max_length=255,
on_delete=models.PROTECT,
related_name='channel',
unique=False,
to_field='category',
)
channel = models.CharField(
max_length=255,
unique=True,
)
def __str__(self):
return self.category
views.py:
class Gallery(viewsets.ModelViewSet):
renderer_classes = [TemplateHTMLRenderer]
template_name = '/gallery.html'
queryset = Category.objects.all()
queryset2 = Channel.objects.all()
permission_classes = [permissions.IsAuthenticated]
def get(self, request, **kwargs):
kwargs['categories_list'] = self.queryset
serializer = CategorySerializer(self.queryset,many=True)
serializer2 = ChannelSerializer(self.queryset2,many=True)
return Response({
'categories':serializer.data,
'channels':serializer2.data
})
# #login_required(login_url='/login/')
def list(self, request):
queryset = Category.objects.all()
response = {'categories': queryset}
return Response({'categories':queryset})
serializers.py:
class CategorySerializer(serializers.ModelSerializer):
# _id = serializers.ReadOnlyField()
categories = Category()
class Meta:
model = Category
fields = '__all__'
class ChannelSerializer(serializers.ModelSerializer):
# _id = serializers.ReadOnlyField()
channels = Channel()
class Meta:
model = Channel
fields = '__all__'
gallery.html:
{% extends "/model-page.html" %}
{% load core_tags %}
{% block content %}
<h1> co. </h1>
<h2> Last Archives </h2>
<a href="/category-api/">
<button type="button"> New input </button>
</a>
<ul>
{% for category in categories %}
<td> {% underscoreTag category "_id" as category_id %} </td>
<div {% if category.get_pass_event %} style="color: red "{% endif %}>
<li>{{ category.category }} - {{ category.get_creation }}
<ul>
<li>{{ category }}</li>
<ul>
<div>
{% for channel in category.channel_set.all %}
<li>Teste {{ channel.title }}</li>
{% endfor %}
</div>
</ul>
</ul>
Edit /
Delete
</li>
</div>
{% endfor %}
</ul>
{% endblock %}
I had trying for {% for channel in category.channel_set.all %},{% for channel in category.channels_set.all %}, {% for channel in category.channel.all %} and {% for channel in category.channels.all %} and any of these worked for me.
Another info from my project is that I'm using Django (because my database is MongoDB).
I think the code of the serializers isn't correct.
class ChannelSerializer(serializers.ModelSerializer):
class Meta:
model = Channel
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
channel = ChannelSerializer(many = True, read_only = True)
class Meta:
model = Category
fields = '__all__'
And in the html, some attributes don't exist in the models. channel_set should be changed into channel and channel.title into channel.channel.
There are no names like channel_set, title in the models.
...
<ul>
<div>
{% for channel in category.channel %}
<li>Teste {{ channel.channel }}</li>
{% endfor %}
</div>
</ul>
...
Or you should modify the names in the models.

Filter Django-Function-View Queryset for User.Request

Models.py
class Experience(models.Model):
user = models.ForeignKey(User, null=True, on_delete = models.CASCADE)
company_name = models.CharField(max_length=100)
company_address = models.CharField(max_length=200)
post_held = models.CharField(max_length=30)
year_from = models.CharField(max_length=20)
year_to = models.CharField(max_length=20)
info = models.TextField()
def get_absolute_url(self):
return reverse('resume')
def __str__ (self):
return self.company_name
Views.py
def Resume(request):
experience = Experience.objects.filter(user = request.user)
return render(request, 'resume.html', {'experience': experience})
Template
<ul>
{% for an_experience in experience %}
<li ><h5>{{ an_experience }},</h5> {{ an_experience.company_address }} - {{ an_experience.post_held }}</li>
<small>{{ an_experience.year_from }} - {{ an_experience.year_to }}</small>
<div>
{{ an_experience.info }}
</div>
{% endfor %}
</ul>
if I use .all(), it is working perfectly but while trying to filter it using request.user nothing is displaying in the template file.

How do i work with 3 django models linked by a foreign field?

I've been able to display all offices in an election, but have been unable to display all candidates in an office on the same page
models.py
class Election(models.Model):
name = models.CharField(max_length = 30)
slug = models.SlugField(max_length = 250, null = False, unique = True)
class Office(models.Model):
election = models.ForeignKey(Election, on_delete=models.CASCADE, default=None)
name = models.CharField(max_length = 30)
class Candidate(models.Model):
office = models.ForeignKey(Office, on_delete=models.CASCADE, default=None)
name = models.CharField(max_length = 30)
views.py
def poll(request, id):
context = {
'election' : Election.objects.get(pk=id),
'off' : Office.objects.all()
}
return render(request, 'poll.html', context)
poll.html
{% for office in election.office_set.all %}
<div class="text-center">
<h3>{{ office.name }}</h3>
{% for candidate in off.candidate_set.all %}
<h5>{{ candidate.name }}</h5>
{% endfor %}
</div>
{% endfor %}
In your first line of poll.html, you call "office" from the queryset "election.office_set.all"
Therefore, when you call a subquery of that QS, you have to reference the original name, ie: office, rather than off.
Your final code should look like this:
poll.html
{% for office in election.office_set.all %}
<div class="text-center">
<h3>{{ office.name }}</h3>
{% for candidate in office.candidate_set.all %}
<h5>{{ candidate.name }}</h5>
{% endfor %}
</div>
{% endfor %}
You also don't need the line
'off' : Office.objects.all()
in your Views.py.

How to show multiple category in detail view django?

I'm working on a Django blog, and having implemented category for detail page. I've stumbled upon an issue.
I want to display some categories of a product by using many to many field, I use the following code.
This my model.py file
from django.db import models
from django.urls import reverse
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('myshop:product_list_by_category', args=[self.slug])
class Product(models.Model):
category = models.ManyToManyField(Category)
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('myshop:product_detail', args=[self.slug])
This is views.py file
from django.shortcuts import render, get_object_or_404
from .models import Category, Product
# Create your views here.
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request, 'shop/product/list.html', {'category': category, 'categories': categories, 'products': products})
def product_detail(request, product_slug):
product = get_object_or_404(Product, slug=product_slug, available=True)
category = product.category.filter(is_active=True)
return render(request, 'shop/product/detail.html', {'product': product}, {'category': category})
and this is for detail.html page file
{% extends "shop/base.html" %}
{% load static %}
{% block title %}
{% if category %}{{ category.title }}{% else %}Products{% endif %}
{% endblock %}
{% block content %}
<div class="product-detail">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}">
<h1>{{ product.name }}</h1>
{% for category in category %}{{ category.name }}{% if not forloop.last %}, {% endif %}
{% endfor %}
<p class="price">${{ product.price }}</p>
{{ product.description|linebreaks }}
</div>
{% endblock %}
I followed the tutorial from Django by Example book.
in the book includes a code to display just one category of each product with the following code
<a href="{{ product.category.get_absolute_url }}">{{ product.
category }}</a>
and I change it to code like above in detail.html file.
Thank you for the help
Try
{% for category in product.category.all %}
{{ category }}
{% endfor %}

how to filter story by it's belonging tag

I have two models news and category, and in news I have foreignkey of category. I know how to display news with same category in a single template. but furthermore, in my home page I'm trying to display featured news of each category. this is where I'm having problem.
this is my models.py
class News(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
category = models.ForeignKey("Tag")
active = models.BooleanField(default=True)
featured = models.BooleanField(default=False)
top = models.BooleanField(default=False)
slug = models.CharField(max_length=255, unique=True)
featuredInCat = models.BooleanField(default=False)
objects = StoryManager()
class NewsQueryset(models.query.QuerySet):
def active(self):
return self.filter(active=True)
def featuredInCat(self):
return self.filter(featuredInCat=True)
class NewsManager(models.Manager):
def get_queryset(self):
return NewsQueryset(self.model, using=self._db)
def get_featuredInCat(self):
return self.get_queryset().active().featuredInCat()
def all(self):
return self.get_queryset().active()
class Category(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(max_length=5000, null=True, blank=True)
In views.py
def category_list(request):
categoryList = NewsCategory.objects.all()
featuredInCat = News.objects.get_featuredInCat()
context = {
"featuredInCat":featuredInCat
"categoryList":categoryList,
}
return render(request,"news/category_list.html", context)
In my template
{% for category in categoryList %}
<div class='col-sm-4'>
<div id="container">{{category.title}}</h1>
<ul>
{% for x in featuredInCat %}
{{x.title}}</li>
{% endfor %}
</ul>
</div>
<hr>
</div>
{% endfor %}
then this shows the featuredInCat in every category where featuredInCat should be shown only in its Category section.
how do I fix this?
Take a look at the built-in regroup template tag of django. You will need to change your template to something like this:
{% regroup featuredInCat by category as news_list %}
<ul>
{% for news in news_list %}
<li>{{ news.grouper.title }}
<ul>
{% for item in news.list %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
You can change your for loop to iterate over the correct objects
{% for x in category.news_set.get_featuredInCat %}
You won't need the context variable anymore

Categories

Resources