Django + HTML Template cannot display the right way - django

I'like to represent the list of news_list, the result should be like following style using 2 loops:
category1
-- info_record 1
-- info_record 2
category2
-- info_record 3
The problem is, inside loop {% for m in p_list.p.name %} always nothing happen, meanwhile outside loop {% for p in p_category %} could be retrieved properly.
html template file is shown as below,
{% block content %}
<div class = "container">
{% for p in p_category %}
<div class = "row" >
......... {{p}}
</br>
</div>
{% for m in p_list.p.name %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}
the view file is shown as below,
from django.shortcuts import render
from datetime import datetime
from .models import Category
from .models import PostInfo
def list_all(request):
post_categories = Category.objects.all()
post_lists ={}
for cate in post_categories:
post_lists[cate.name] = PostInfo.objects.all().filter(category = cate)
import pdb; pdb.set_trace()
return render(request, 'pub_post.html', {'p_category': post_lists.keys(), "p_list": post_lists})
model file is shown as below,
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200,
db_index=True)
slug = models.SlugField(max_length=200,
db_index=True,
unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
class PostInfo(models.Model):
title = models.CharField(max_length=200,
db_index=True)
slug = models.SlugField(max_length=200,
db_index=True,
unique=True)
content = models.TextField(blank=True,
null=True)
category = models.ForeignKey(Category,
related_name='post_category')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, related_name='created_by_user')
updated_by = models.ForeignKey(User, related_name='updated_by_user')
class Meta:
ordering = ('updated',)
# verbose_name = 'post'
# verbose_name_plural = 'posts'
def __str__(self):
return self.title
Appreciated if any one could give me your hand, thanks a lot again.

Thats because p_list is a dictionary.
Try this:
{% for key, value in p_list.items %}
{% if key == p %}
{% for m in value %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endif %}
{% endfor %}
.items convert the dictionary into a list of (key, value) pairs
Update, you can just replace the whole template with this and avoid the context variable p_category
{% block content %}
<div class = "container">
{% for p, values in p_list.items %}
<div class = "row" >
......... {{p}}
</br>
</div>
{% for m in values %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}

Related

Can I access the child model from the parent?

I have created a productForArt and albomForArt model
From producForArt I inherit to albomForArt
Making a view based on generic.ListView
And I output it in the template,
Can I access the number Of Pages field in the template
albomForArt models, or in this case Django returns an object of the albomForArt model, but with properties that were inherited from albomForArt?
models
from django.db import models
class productForArt(models.Model):
class Meta:
verbose_name = u'товар'
verbose_name_plural = u'товары'
price = models.IntegerField(verbose_name="цена", default=0)
title = models.CharField(max_length=300, verbose_name="название товара", null=True)
description = models.CharField( max_length=1000,verbose_name="Описание товара", null=True)
type = models.ForeignKey('typeProductForArt', on_delete=models.PROTECT)
def getType(self):
return self.type
def __str__(self):
return str(self.title) + ' по цене' + str(self.price) + ' шт'
class albomForArt(productForArt):
numberOfPages = models.IntegerField(default=10,verbose_name="количество станиц" )
class typeProductForArt(models.Model):
title = models.CharField(max_length=200, default="none")
def __str__(self):
return self.title
vievs
from django.views import View, generic
from .models import productForArt
class startPage(generic.ListView):
model = productForArt
template_name = "startPage.html"
context_object_name = "productForArt_list"
queryset = productForArt.objects.all()[:20]
templates
{% if productForArt_list %}
<section class="productsStartpage">
{% for productForArt in object_list %}
<article class="productForArtStartpage">
<h1>{{productForArt.title}}</h1>
<p>{{productForArt.description}}</p>
{% endif %}
</article>
{% endfor %}
</section>
{% else %}
<p>товара нету</p>
{% endif %}
You can use One-to-one relationships
class albomForArt(productForArt):
product_for_art = models.OneToOneField(productForArt, on_delete=models.CASCADE)
numberOfPages = models.IntegerField(default=10,verbose_name="количество станиц" )
Then in Template
{% if productForArt_list %}
<section class="productsStartpage">
{% for productForArt in object_list %}
<article class="productForArtStartpage">
<h1>{{productForArt.product_for_art.title}}</h1>
<p>{{productForArt.product_for_art.description}}</p>
{% endif %}
</article>
{% endfor %}
</section> {% else %} <p>товара нету</p>{% endif %}

Django Display count of database entries related via foreign key

I have two models, ProjectNotes and ProjectNoteComments. ProjectNoteComments are related to ProjectNotes via a foreign key. I want to display the number of comments each note has on a listview. I am just learning Django and so far I have not been able to figure out how to retrieve and display the comment count.
My view:
(I do import count)
class ProjectNotesList(ListView):
model = ProjectNotes
template_name = 'company_accounts/project_notes.html'
comments = ProjectNotes.comments
def related_project(self, **kwargs):
project = get_object_or_404(Project, id=self.kwargs.get('pk'))
notes = ProjectNotes.objects.all
return notes
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context['project'] = get_object_or_404(Project, id=self.kwargs.get('pk'))
return context
commentscount = ProjectNotes.objects.annotate(num_comments=Count('comments'))
My template:
{% extends 'base.html' %}
{% block content %}
<div class="section-container container">
<h1>Notes for {{ project }}</h1>
{% if project.notes.all %}
{% for note in project.notes.all %}
<div class ="projectnotes-entry">
<div class="col-sm-8">
<div class="row-sm-6">
<div class="card mb-2">
<div class="card-body">
<div class="card-title">{{ note.title }}</div>
<div class="card-text">{{ note.body | safe | truncatewords:"20"|linebreaks }}
read more</div>
</div>
</div>
</div>
</div>
</div>
<h2>comments count</h2>
{{ commentscount }}
{% endfor %}
{% else %}
<p>No notes have been have been added yet.</p>
{% endif %}
</div>
{% endblock content %}
The models:
class ProjectNotes(models.Model):
title = models.CharField(max_length=200)
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
project = models.ForeignKey(Project, default=0, blank=True, on_delete=models.CASCADE, related_name='notes')
def __str__(self):
return self.title
class ProjectNoteComments(models.Model):
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
projectnote = models.ForeignKey(ProjectNotes, default=0, blank=True, on_delete=models.CASCADE, related_name='comments')
Short version:
{{ note.comments.all.count }} # possibly works also without 'all' but can't check right now
I've just answered similar problem with simple explanation of relationships.
https://stackoverflow.com/a/70955851/12775662
Read official docs, it's really rewarding. https://docs.djangoproject.com/en/4.0/topics/db/models/#relationships

How can I include a template inside another template?

Im new to programming and I looking if there is there a way that I can include a template inside other template. Im working on a project that I want to display on the same page a content of a certain topic and flashcards to test my knowledge of this topic, and Im stuck when trying to display my cards on the same page (I could only make it work using another url). Here is what I have so far:
models.py:
class Topic(models.Model):
author = models.ForeignKey(
User, related_name="topic", on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=100)
body = RichTextUploadingField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=120)
class Meta:
ordering = ["title"]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('topic:topic-detail', kwargs={
"topic_slug": self.slug,})
class Deck(models.Model):
deckTopic = models.ForeignKey(
Topic, null=True, blank=True, on_delete=models.CASCADE)
description = models.CharField(max_length=510, null=False, blank=True)
is_active = models.BooleanField(default=False)
def __str__(self):
return self.description
def get_number_of_cards(self):
'''
Returns the number of cards in the decks related card_set
'''
return self.card_set.count()
get_number_of_cards.short_description = 'Card Count'
class Card(models.Model):
parentDeck = models.ForeignKey(Deck, on_delete=models.CASCADE)
front = models.TextField()
back = models.TextField()
def __str__(self):
return self.front
def has_prev_card(self):
'''
Returns true if card is not thee first card in the deck.
'''
first_card_in_deck = self.parentDeck.card_set.first()
if self == first_card_in_deck:
return False
return True
def get_prev_card(self):
'''
Return previous card in deck
'''
return self.parentDeck.card_set.filter(id__lt=self.id).last()
def has_next_card(self):
'''
Returns true if card is not the last card in the deck.
'''
last_card_in_deck = self.parentDeck.card_set.last()
if self == last_card_in_deck:
return False
return True
def get_next_card(self):
'''
Return next card in deck
'''
return self.parentDeck.card_set.filter(id__gt=self.id).first()
views.py:
class TopicDetailView(DetailView):
model = Topic
def viewDeck(request, deck_id):
'''
Gets the deck from the database.
Return first card in deck unless card_id is specified in url.
'''
deck_obj = get_object_or_404(Deck, id=deck_id)
card_list = deck_obj.card_set.all()
card_obj = card_list.first()
if request.method == 'GET' and 'card' in request.GET:
card_obj = get_object_or_404(Card, id=request.GET['card'])
context = {
'deck_obj': deck_obj,
'card_obj': card_obj,
}
return render(request, 'topic/viewDeck.html', context)
topic_detail.html:
{% extends 'base.html' %}
{% block content %}
<div class="topic-title">
<h5 class="mb-0">
{{object.title}}
</h5>
</div>
<div class="topic-body">
<p class="mb-0">
{{object.body}}
</p>
</div>
<!--Here is where I want to include the flashcard--!>
<div class="topic-deck">
{% for deck in object.deck_set.all %}
{{deck.description}}
Flashcard
{% endfor %}
</div>
{% endblock %}
viewDeck.html:
{% extends 'base.html' %}
{% block content %}
<div class="deck-container">
<div class="deck-header">
<div class="deck-header-title">
<h1>{{deck_obj}}</h1>
</div>
<div class="deck-header-actions">
<p>Return to Topic</p>
</div>
</div>
<hr>
{% if card_obj %}
<div class="notecard">
<div class="notecard-nav text-center">
{% if card_obj.has_prev_card %}
<a href="{% url 'topic:viewDeck' deck_obj.id %}?card=
{{card_obj.get_prev_card.id}}">Prev</a>
{% endif %}
{% if card_obj.has_next_card %}
<a href="{% url 'topic:viewDeck' deck_obj.id %}?card=
{{card_obj.get_next_card.id}}">Next</a>
{% endif %}
</div>
<div class="notecard-front">
<p class="text-center">Front</p>
<p>{{card_obj.front}}</p>
</div>
<div class="notecard-back">
<p class="text-center">Back</p>
<p>{{card_obj.back}}</p>
</div>
</div>
{% else %}
<p>No card found.</p>
{% endif %}
</div>
{% endblock %}
Is there a way to see deckView inside topic_detail.html? Sorry if I didn't made myself clear.
Update:
I tried inserting {% include 'viewDeck.html' %} as passing the context deck_obj, card_list and card_obj to topic_detail.html, but it gives me this error: NameError: name 'deck_id' is not defined. How can I fix this?
Thank you.
Did you build the url correctly ?
To be able to pass the deck_id like you did in your view, you have to tell your url that you want to pass some data in, by writing something like this in your urls.py :
from name_of_your_app import views
url(r'deck/(?P<deck_id>\d+)/$', views.viewDeck , name='name_of_you_url'),
(?P<deck_id>\d+) is the important part, as it indicates that you will receive a numerical data which can be called with the name "deck_id".

How can I grab articles with the same tag, so within a template I can display those articles?

I'm new to Django, so thanks for any help.
I have an Article model, and I would like to display related/similar articles by assigning tags to each article.
I've tried making a function/filter in my views.py that inherits from self (that particular article) and filters out the articles with the same tag, but with no success.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200, blank=True)
thumbnail = models.ImageField(max_length=200, blank=True)
tag = models.CharField(max_length=200, blank=True)
from .models import Article
class ArticleView(DetailView):
template_name = "article/article.html"
model = Article
def related_articles(self):
tagged = Article.objects.filter(tag=self.tag)
return tagged
{% if articles.objects.all %}
{% for article in article.objects.all|related_articles %}
<div>
<img src="{{ article.thumbnail.url }}">
<span>{{ article.title }}</span>
</div>
{% endfor %}
{% endif %}
So, whenever I try to use this filter I get no results.
I think the related_articles function should be on the model class.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200, blank=True)
thumbnail = models.ImageField(max_length=200, blank=True)
tag = models.CharField(max_length=200, blank=True)
def related_articles(self):
tagged = Article.objects.filter(tag=self.tag).exclude(pk=self.pk)
Suppose your have a view like this:
def articles(request):
articles = Articles.objects.all()
context = dict(articles=articles)
return render(request, 'app/articles.html', context)
You could have a template like this:
{% if articles|length %}
{% for article in articles %}
<div>
<img src="{{ article.thumbnail.url }}">
<span>{{ article.title }}</span>
{% for related_article in article.related_articles %}
<span>{{ related_article.title }}</span>
{% endfor %}
</div>
{% endfor %}
{% endif %}

Get Featured Image from different Model

I have 2 model objects, Business & BusinessImage as so, listed with views and index.html. I am trying to list the business's featured image, but it's not happening. I am getting the following error:
'QuerySet' object has no attribute 'businessimage_set'
How can I get the business featured image for a list?
Business
class Business(models.Model):
name = models.CharField("Name", max_length=70, default="Business Name")
slug = models.SlugField()
description = models.TextField("About", max_length=400)
category = models.ManyToManyField(Category, verbose_name="Categories", blank=True)
order = models.IntegerField("Order", default=0)
claimed = models.BooleanField("Claimed", default=False)
featured = models.BooleanField("Featured", default=False)
class Meta:
ordering = ['order']
verbose_name = "Business"
verbose_name_plural = "Businesses"
def __str__(self):
return self.name
BusinessImage
class BusinessImage(models.Model):
business = models.ForeignKey(Business)
image = models.ImageField(upload_to="images/business")
title = models.CharField(max_length=120)
featured = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return self.title
view.py
from .models import Business, BusinessImage
def index_view(request):
latest_business_list = Business.objects.all()
images = latest_business_list.businessimage_set.all()
template = loader.get_template('index.html')
context = RequestContext(request, {
'latest_business_list': latest_business_list,
'images': images,
})
return HttpResponse(template.render(context))
index.html
{% block content %}
<div class="text-center business_title">
<h2>Featured</h2>
</div>
{% if latest_business_list %}
{% for business in latest_business_list|slice:":4" %}
{% if business.active %}
<div class="col-sm-6 col-md-3">
<li>{{ business.name }}</li>
{% for image in latest_business_list.businessimage_set.all %}
{% if image.featured %}
<a href="{% url 'single_product' product.slug %}">
<img src="{{MEDIA_URL}}{{image.image}}" alt="{{image}}">
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
businessimage_set is an attribute of a Business instance, but you're trying to access it as an attribute of a queryset (i.e. list of businesses). If your goal is just to be able to access the images for each business in a template, you can leave out images entirely. Instead your template would have:
{% for image in business.businessimage_set.all %}
(Though look into prefetch_related for efficiency.)