Template in Django doesn't show same content for 2 paths - python

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>

Related

Could not parse the remainder:

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>

Django - Looping over unique model field in template

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>

Django: Showing "featured" items?

I'm having a little conundrum with sorting some items. I have a field called featured thats a boolean. I'm trying to display the featured coins first and then the remaining will be sorted by a different metric. In this code im using pub_date.
However, when I put an if statement in my template for the featured items it's still showing those that are set to false as well. I'll post code below.
index.html loops and if's
{% if featured_coins_list %}
{% for coin in featured_coins_list %}
<div class="large-6 medium-6 cell">
<h2>{{ coin.name }}</h2>
<p>Ticker: {{ coin.ticker }}</p>
<p>{{ coin.summary }}</p>
More Info</strong>
</div>
{% endfor %}
{% endif %}
{% if latest_coins_list %}
{% for coin in latest_coins_list %}
<div class="large-6 medium-6 cell">
<h2>{{ coin.name }}</h2>
<p>Ticker: {{ coin.ticker }}</p>
<p>{{ coin.summary }}</p>
More Info</strong>
</div>
{% endfor %}
</div>
{% else %}
<p>No coins are available.</p>
{% endif %}
views.py for index
def index(request):
featured_coins_list = Coin.objects.order_by('-featured')[:4]
latest_coins_list = Coin.objects.order_by('-pub_date')[:8]
context = {'featured_coins_list': featured_coins_list,
'latest_coins_list': latest_coins_list}
return render(request, 'coins/index.html', context)
models.py
class Coin(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
ticker = models.CharField(max_length=5)
featured = models.BooleanField(default=False)
logo = models.ImageField(upload_to='uploads/', verbose_name='image')
website = models.URLField(max_length=200, default="https://example.com/")
reddit = models.URLField(max_length=200, default="https://reddit.com/r/")
twitter = models.URLField(max_length=200, default="https://twitter.com/")
summary = models.CharField(max_length=500, blank=True)
description = models.TextField()
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.ticker
def is_featured(self):
return self.featured
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
How should I go about listing the featured coins that are set to true first and then display the remaining items after?
You need to filter for featured=True in your queryset.
def index(request):
featured_coins_list = Coin.objects.filter(featured=True).order_by('-featured')[:4]
latest_coins_list = Coin.objects.order_by('-pub_date')[:8]
context = {'featured_coins_list': featured_coins_list,
'latest_coins_list': latest_coins_list}
return render(request, 'coins/index.html', context)

Sending iterable object to base template (ex: ' menus = Menu.objects.all() ')

When I send
menus = Menu.objects.all()
through render
render(request, 'index.html', {'menus': menus})
it did not show me anything, just empty page
But other variables like
info = Info.objects.last()
is working properly
this is view.py
'''some code here'''
def home(request):
slides = Slide.objects.order_by('created')[:3]
main_articles = MainArticle.objects.order_by('created')[:5]
last_news = News.objects.all()[:4]
info = OtherInfo.objects.last()
promo = Promo.objects.last()
menus = Menu.objects.all()
return render(request, 'index.html', {'slides': slides,
'main_articles': main_articles,
'last_news': last_news,
'info': info,
'promo': promo,
'menus': menus
})
This is models.py
class Menu(models.Model):
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Meta:
ordering = ('created',)
class SubMenu(models.Model):
menu = models.ForeignKey(Menu, related_name='sub_menu')
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} -> {}'.format(self.menu, self.name)
class Meta:
ordering = ('created',)
'''some other models here'''
this is index.html
{% extends 'base.html' %}
{% block nav_bar %}
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
{% for m in menus.all %}
{% if m.sub_menu %}
<li class="dropdown">
{{ m.name }}<span class="caret"></span>
<ul class="dropdown-menu">
{% for sub in m.sub_menu.all %}
<li>{{ sub.name }}</li>
{% endfor %}
</ul>
</li>
{% else %}
<li>
{{ m.name }}
</li>
{% endif %}
{% endfor %}
</ul>
</div><!-- /.navbar-collapse -->
{% endblock %}
If you pass:
menus = Menu.objects.all()
you can use in your template:
{% for menu in menus %}
...
{% if menu.sub_menu.exists %}
{% for submenu in menu.sub_menu.all %}
....
You did already call .all() in your view.

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