I saw many questions about this error, but all are distincts and not apply to me, so...
My models.py
# Category
class Category(models.Model):
category_name = models.CharField(max_length=64)
def __str__(self):
return f"{self.category_name}"
# Item
class Item(models.Model):
item_name = models.CharField(max_length=64)
category = models.ForeignKey(Category, on_delete= models.CASCADE, related_name="items_by_category")
price_small = models.DecimalField(help_text="Price in U$S",max_digits=6, decimal_places=2, default= 0)
price_large = models.DecimalField(help_text="Price in U$S",max_digits=6, decimal_places=2, default= 0)
nradd = models.IntegerField(default=0)
def __str__(self):
return f"{self.category} {self.item_name} - Qty.of Adds: {self.nradd} - Price Small: {self.price_small} - Price Large: {self.price_large}"
My views.py
def menu(request):
products = list(Item.objects.all().values().order_by('category'))
categories = list(Category.objects.all().prefetch_related('items_by_category'))
extras = list(Extra.objects.filter(category="T"))
subsextras = list(Extra.objects.filter(category="S"))
context = {
'Products' : products,
'Categories': categories,
'Extras' : extras,
'Subextras' : subsextras
}
return render(request, 'orders/menu.html',context)
First, I'm trying to simply list the categories with the items who belongs to:
My menu.html:
{% extends 'orders/base.html' %}
{% load static %}
{% block title %}
Menu
{% endblock %}
{% block body %}
<ul>
{% for cate in Categories %}
<li>{{ cate.category_name }}</li>
<ul>
{{% for myitem in cate.items_by_category.all %}}
<li>{{ myitem.item_name }}</li>
{{% endfor %}}
</ul>
{% endfor %}
</ul>
{% endblock %}
the error appears in the line:
{{% for myitem in cate.items_by_category.all %}}
Same commands in the shell goes well:
cate = Category.objects.get(category_name="Salads")
cate.items_by_category.all()
Thanks in advance,
It's about Template Language.
Variables look like this: {{ variable }}.
Filters look like this: {{ name|lower }}.
Tags look like this: {% tag %}.
To comment-out part of a line in a template, use the comment syntax:
{# #}
There is no such thing as {{% %}}
So, instead of
{{% for myitem in cate.items_by_category.all %}}
You should use
{% for myitem in cate.items_by_category.all %}
Reference:
https://docs.djangoproject.com/en/3.0/ref/templates/language/
The template tags are sourrounded with {% … %}, not {{% … %}}. So you should rewrite the template to:
{% extends 'orders/base.html' %}
{% load static %}
{% block title %}
Menu
{% endblock %}
{% block body %}
<ul>
{% for cate in Categories %}
<li>{{ cate.category_name }}</li>
<ul>
{% for myitem in cate.items_by_category.all %}
<li>{{ myitem.item_name }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
Related
I have a model which a choice field, category, which the user must enter when submitting an entry. I would like to create a view in which each category has its own heading (only once), therefore each unique category would have its own heading, and then display the title associated to each category.
models.py
class Position(models.Model):
club_functions = Choices('Corporate Relations', 'Events & Conference', 'Marketing & Operations', 'Software Development', 'Product')
title = models.CharField(max_length=50)
category = models.CharField(choices=club_functions, max_length=30, blank=False)
description = models.TextField(blank=True)
spec_q1 = models.CharField(max_length=500)
spec_q2 = models.CharField(max_length=500)
views.py
def position_list_view(request):
all_objects = Position.objects.all()
context = {
'object_list' : all_objects
}
return render(request, "exec_list.html", context)
exec_list.html
{% for object.category in object_list %}
<h3>{{ object.category }}</h3>
<p>{{ object.title }}</p>
{% endfor %}
Any ideas on how to do this?
you can use regroup
{% regroup object_list by category as category_list %}
<ul>
{% for category in category_list %}
<li>{{ category.grouper }}
<ul>
{% for position in category.list %}
<li>{{ position.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
For this template, everything will show fine, but only for the first course. If I add lectures for another course, template won't show them.
def courses(request, slug):
con = get_object_or_404(Course, slug=slug)
context = {
'course': con,
'lectures': con.lectures.all(),
'categories': con.categories.all(),
}
return render(request, 'courses/courses.html', context)
<ul>
{% for a in categories %}
<li><strong>{{ a.course_category }}</strong></li>
{% for c in lectures %}
{% if a == c.course_category %}
<li>{{ c.lecture_title }}</li>
<li>{{ c.content }}</li>
{% if c.link %}
<li>{{ c.link }}</li>
{% endif %}
{% if c.file %}
<li><a href='{{ MEDIA_URL }}{{ c.file.url }}'>download</a></li>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
class Course(models.Model):
study_programme = models.ForeignKey('StudyProgramme', on_delete=models.CASCADE)
name = models.CharField(max_length=50)
ects = models.PositiveSmallIntegerField(validators=[MaxValueValidator(99)])
description = models.TextField()
year = models.PositiveSmallIntegerField(validators=[MaxValueValidator(99)])
semester = models.IntegerField(choices=((1, "1"),
(2, "2"),
), default=None)
slug = models.SlugField(max_length=140, unique=True)
def __str__(self):
return self.name
def _get_unique_slug(self):
slug = slugify(self.name)
unique_slug = slug
num = 1
while Course.objects.filter(slug=unique_slug).exists():
unique_slug = '{}-{}'.format(slug, num)
num += 1
return unique_slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self._get_unique_slug()
super().save()
class CourseCategory(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE, related_name='categories')
course_category = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.course_category
class Lecture(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE, default='', related_name='lectures')
This is the Course model that is present in my models.py. It uses slug for links.
I think your Lecture model has a problem.
Why does your Lecture model's course field has default=''?
It should be one of your Courcse model objects. If you want to add default value, you can use like this
DEFAULT_COURSE = 1
class Lecture(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE, default=DEFAULT_COURSE, related_name='lectures')
Hope this helps:
You need two views for this, each doing only the database queries they actually need and handle all the data preparation.
This way, you get nice and clean templates.
First View: /courses
def courses(request):
queryset = Course.objects.all()
context = {'courses':queryset}
return render(request, 'courses/courses.html', context)
template for this (courses.html):
<ul>
{% for i in courses %}
<li>
<a href={{ i.slug }}>{{ i }}</a>
</li>
{% endfor %}
</ul>
Second View: /courses/course_name
def course_detail(request, course_name):
query = Course.object.get(name=course_name)
context = {'lectures':query.lectures.all(),'categories':query.categories.all()}
return render(request, 'courses/course_detail.html', context)
template for this (course_detail.html):
<p><strong>Categories</strong></p>
<ul>
{% for c in categories %}
<li>{{ c.course_category }}<li>
{% endfor %}
</ul>
<p><strong>Lectures</strong></p>
<ul>
{% for l in lectures %}
<li>{{ l.lecture_title }}</li>
<li>{{ l.content }}</li>
{% if l.link %}
<li>{{ l.link }}</li>
{% endif %}
{% if l.file %}
<li><a href='{{ MEDIA_URL }}{{ l.file.url }}'>download</a></li>
{% endif %}
<hr>
{% endfor %}
</ul>
I created model, view and template for display list of items in template but after I run the website It didn't anything. Please help me to solve this.
model.py
class waterLevel(models.Model):
height = models.CharField(max_length=250)
date = DateTimeField(max_length=250)
def __str__(self):
# #
return self.height + '-' + self.date
view.py
def compare(request):
all_waterLevels = waterLevel.objects.all()
context = {'all_waterLevels': all_waterLevels}
return render(request, 'Home/compare.html', context)
compare.html
{% if all_waterLevels %}
<ul>
{% for height in all_waterLevels %}
<li> {{ waterLevel.height }}</li>
<li> {{ waterLevel.date }}</li>
{% endfor %}
</ul>
{% else %}
<h3>no any details</h3>
{% endif %}
Try this :
{% if all_waterLevels %}
<ul>
{% for waterLevel in all_waterLevels %}
<li> {{ waterLevel.height }}</li>
<li> {{ waterLevel.date }}</li>
{% endfor %}
</ul>
{% else %}
<h3>no any details</h3>
{% endif %}
Consider the following model:
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
POSITIONS = (
('L', 'Left'),
('R', 'Right')
)
position = models.CharField(max_length=1, choices=POSITIONS, default='R')
class Meta:
verbose_name_plural = 'categories'
def __str__(self):
return self.name
I want to sort the objects in a manner such that I can separate the left ones from the right ones and show them in separate parts of the html document. Something like:
{% for category in categories|sort_by: "position" = "left" %}
<ul class="collection with-header">
<li class="collection-header">
<h3>{{category.name}}</h3>
<p><small>{{category.description}}</small></p>
</li>
{% for url in category.extra_link_set.all %}
<li class="collection-item">{{url.url_text}}</li>
{% endfor %}
</ul>
{% endfor %}
I know this wont work. But I am just trying to give an idea as to what I want. Also would the process be similar for any other field type in django models?
You could try something like this:
{% for category in categories %}
<div class="left_stuff">
{% if category.position=='L' %}
<h3>...</h3>
.....
{% endif %}
</div>
{% endfor %}
{% for category in categories %}
<div class="right_stuff">
{% if category.position=='R' %}
<h3>...</h3>
.....
{% endif %}
</div>
{% endfor %}
In my Django template I want to be able to iterate through groups and items, but I want to iterate the items underneath their group. So far I have them iterating like this but it does not show which groups the items are a part of. How would I iterate the template to get this inclusion?
Views:
def manage(request):
group_list = Group.objects.order_by('name').filter(user=request.user)
item_list = Item.objects.order_by('name').filter(user=request.user)
return render(request, 'manage.html', {'group_list': group_list, 'item_list': item_list})
Template:
{% extends "base.html" %}
{% block content %}
{% for group in group_list %}
{{ group.name }}<br />
{% endfor %}
{% for item in item_list %}
{{ item.name }}<br />
{% endfor %}
{% endblock %}
UPDATE
Models (Sorry forgot to include this):
class Group(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=30)
class Item(models.Model):
user = models.ForeignKey(User)
group = models.ManyToManyField(Group)
name = models.CharField(max_length=30)
Your approach does unneccessary additional database hits. For performance reasons you should select just the items with related groups like this:
def manage(request):
item_list = Item.objects.order_by(
'group__name', 'name').filter(
user=request.user).select_related('group')
return render(request, 'manage.html', {'item_list': item_list})
The template looks like this:
{% extends "base.html" %}
{% block content %}
{% for item in item_list %}
{% ifchanged item.group.name %}
{{ item.group.name }}<br />
{% endifchanged %}
{{ item.name }}<br />
{% endfor %}
{% endblock %}
That way you only have ONE database hit regardless of how many groups there are.
I guess you have a fk from item to group
class Item(models.Model):
group = models.ForeignKey(Group)
views:
def manage(request):
group_list = Group.objects.order_by('name').filter(user=request.user)
return render(request, 'manage.html', {'group_list': group_list})
template:
{% extends "base.html" %}
{% block content %}
{% for group in group_list %}
{{ group.name }}<br />
<p>Item for this group</p>
{% for item in group.item_set.all %}
{{item.name}}
{% endfor %}
{% endfor %}
{% endblock %}