How to make a div appear only once in a loop? - django

I've created a model Team in models.py in Django for which I've created in views.py the following code:
def team(request):
obj = Team.objects.all().order_by('?')
context = {'team': obj}
return render(request, 'website/team.html', context)
In HTML I've created a team loop which is displaying all the team members available.
{% for team in team %}
<div class="member animated delay1" data-effect="fadeInUp">
<div class="team-image">
<div class="teamDescription">
<p>{{ team.description }}</p>
</div>
<img src="{{ team.picture.url }}">
</div>
<div class="blueLine"></div>
<div class="team-name-function animated delay1" data-effect="fadeInUp">
<h5>{{ team.name }} {{ team.surname }}</h5>
<p>{{ team.title }}</p>
</div>
</div>
{% endfor %}
In this loop, I need to make available one div with the numbers of team members, which has to appear only once and randomly as team members. Currently I have <div class="number">{{ team.count }}</div> outside the loop.
How do I integrate the members counting in the loop and make it appear only once?
Thank you in advance for any solution!

In the view use teams instead of team: context = {'teams': obj}
create a random number between 1 and teams length in view
import random
....
random_number = random.randint(a,len(teams)) # insert it after teams
...
context = {
'team': obj,
'random' : random_number,
}
then in the template use {% for team in teams %}
and if you want to show teams length just one time it's possible to use
{% if forloop.counter==random %}
<div class="number">{{ teams.count }}</div>
{% endif %}

Related

For loop inside a IF condition to show right category on django template

I'm trying to show the correct articles in the category section using an if condition with a for loop inside, so far I'm displaying all the articles and not the only ones that supposed to be in the category.
home.html screeenshot
home.html
{% if articles.category == Sports %}
{% for article in articles %}
<div class="position-relative">
<img class="img-fluid w-100" src="{{article.cover.url}}" style="object-fit: cover;">
<div class="overlay position-relative bg-light">
<div class="mb-2" style="font-size: 13px;">
{{article.title}}
<span class="px-1">/</span>
<span>{{article.created_at}}</span>
</div>
<a class="h4 m-0" href="">{{article.description}}</a>
</div>
</div>
{% endfor %}
{% endif %}
views.py
def home (request):
cats = Category.objects.all()
articles = Article.objects.filter( is_published=True).order_by('-category')
return render (request,'pages/home.html',
context={
'cats': cats,
'articles': articles
})
Instead of hardcoding it like that, you could let the users search for categories with something like this:
articles = Article.objects.filter(category__icontains=q).values('title')
where q would be the user input in the form.

Have issues getting data to display on my web application

I am trying to get the "About us" information from my database to my web application but its not displaying, what could be wrong...
here is the code from the database
class About(models.Model):
about_us = models.TextField()
achieve = models.TextField(blank=True)
image_abt = models.ImageField(upload_to="admin_pics", null=True)
class Meta:
verbose_name_plural = "About Us"
def __str__(self):
return self.about_us
and here is the Html code `
{% extends 'jtalks/base.html' %}
{% load static %}
{%block content%}
<section id="about-home">
<h2>About Us</h2>
</section>
<section id="about-container">
{% for about in abouts %}
<div class="about-img">
<img src="{{ about.image_abt.url }}" alt="">
</div>
<div class="about-text">
<h2>Welcome to TechEduca, Enhance your skills with best Online Courses</h2>
<p>{ about.about_us}</p>
<div class="about-fe">
<img src="images/fe1.png" alt="">
<div class="fe-text">
<h5>400+ Courses</h5>
<p>You can start and finish one of these popular courses in under our site</p>
</div>
</div>
<div class="about-fe">
<img src="images/fe2.png" alt="">
<div class="fe-text">
<h5>Lifetime Access</h5>
<p>You can start and finish one of these popular courses in under our site</p>
</div>
</div>
</div>
{% endfor %}
</section>
{% endblock %}
Nothing is displaying in the frontend of the website.
Thanks for sharing the view. You forgot to pass data to your template. To do that you have to create the queryset and pass that into a dictionary like below. Add the context variable to your render method so you can access the data in the template.
def about(request):
about = About.objects.all()
context = {
'abouts': about,
}
return render(request, 'jtalks/about.html', context)
also, in your html code i see { about.about_us}, but you have to use double curly brackets: {{ about.about_us }}

Getting an empty query set Django

I'm trying to develop a search functionality but only getting a empty query set every single time .
class SearchView(TemplateView):
template_name = "search.html"
def get_context(self, **kwargs):
context = super().get_context(**kwargs)
kw = self.request.GET.get("search")
results = Thread.objects.filter(Q(heading__icontains=kw) | Q(thread_content__icontains=kw))
print(results)
context["results"] = results
return context
Template
{% extends 'base.html' %}
{% block title %}Search{% endblock %}
{% block content %}
<div class = "container">
<div class = "row">
<div class = "col-md-12">
<h3>Search results for <span class="text-info">"{{ request.GET.search }}"</span></h3>
<h3>{{results}}</h3>
<hr>
{% for item in results %}
<div class="col-md-4">
<img src = "{{item.image.url}}" class="img-fluid" alt = "">
</div>
<div class="col-md-8">
<h4>{{item.heading}}</h4>
<p>{{item.thread_content}}</p>
</div>
{%endfor%}
</div>
</div>
</div>
{% endblock %}
request.GET.search is returning correctly , but the rest is not getting displayed
This was a real strange issue. The Browser cache took a long time to refresh with my updated code. Once I cleared the Browser Cache and Settings, it started working again.

Django iteration (for ... in ...) how to put it in different divs?

I have few instances of model.
my model:
class Record(models.Model):
name = models.ForeignKey(Car)
image = models.ImageField(upload_to='images/')
created = models.DateTimeField(
default=timezone.now)
view:
def allrecords(request):
records = Record.objects.all().order_by('created')
return render(request, 'mycar/allrecords.html', {'records' : records})
I want show it on my website. In my template i have:
{% for record in records %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endfor %}
Now i get list of my records, but i would like put the newest record to first div, next to second etc. How can i do that?
I show simple screen how i would like have that (if someone will create new record, it will go to first div and other records will change place. Is any possibility to do something like that?
edit:
<div>
{% for record in records %}
{% if forloop.counter == 1 %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
{% endfor %}
</div>
<div>
{% for record in records %}
{% if forloop.counter == 2 %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
{% endfor %}
</div>
.
.
# till your 5th image
You can use forloop.counter to get the iteration number and check what is the iteration the loop and handle data accordingly.
In addition you can use CSS to make the layout work as you want.
Here is the information for Django template counter
Edit :
{% for record in records %}
<div>
{% if forloop.counter == 1 %}
# Here you can get your first images
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
</div>
<div>
{% if forloop.counter == 2 %}
# Here you can get your first images
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
</div>
.
.
# till your 5th image
{% endfor %}
There are two ways to do this. If you want to set this option for a single view then:
def all_records(request):
records = Record.objects.all().order_by('-created')
return render(request, 'mycar/allrecords.html', {'records' : records})
You're almost correct but order_by('created') leads to asceding order while order_by('-created') leads to descending order which is what you require.
Alternatively, if you want to have this setting to apply to all views then set class Meta in your models.py which will ensure that wherever you use Record.objects.all() it returns Records in descending order of created field:
class Record(models.Model):
name = models.ForeignKey(Car)
image = models.ImageField(upload_to='images/')
created = models.DateTimeField(
default=timezone.now)
class Meta:
ordering = ('-created')
It's Django design pattern to make all logical decisions in models and views and only just plugin formatted data in templates. You shouldn't add any complex logic in templates.
I'm assuming the question means that the model might have more than 5 records. If so, a more generic solution would be
<div class='row'>
<div class='firstimage'>
<img src={{ records[0].image.url}}/>
{{record.name}}
</div>
{% for record in records %}
{% if forloop.counter > 1 %}
<div class='subsequentimage'>
<img src={{ record.image.url}}/>
{{record.name}}
</div>
{% endif %}
{% cycle "" "</div><div class='row'>" "" %}
{% endfor %}
</div>
Note the use of the 'cycle' tag to begin a new row div every third cell div.
I don't know what your CSS classes are to distinguish between rows and cells so I used 'row', 'firstimage' (which might be defined to take up twice as much width) and 'subsequentimage' as example classes.
I recommend you to use the context variables:
def all_records(request):
records = Record.objects.all().order_by('-created')
newest = records[:5]
oldest = records[5:]
return render(request, 'mycar/allrecords.html', {'newst' : newest,
'oldest': oldest })
In your template :
{% for new in newst %}
<div>what you want with news</div>
{% endfor %}
{% for old in oldest %}
<div>what you want with olds</div>
{% endfor %}

combine number of database requests using ORM

I am working on a website, where a user can vote and comment on different projects in various categories. Whenever a user returns to the site, their votes will be highlighted and all the comments will be visible.
The problem is that every time the page is loaded there are many database calls due to the design of my models or due to me not finding an efficient way of retrieving the data.
My models are as follows:
class ProjectCategory:
title=models.CharField(...)
class Project:
category=models.ForeignKey(ProjectCategory)
title=models.CharField(...)
def ownedComments(self):
return Comment.objects.filter(project=self).order_by('-submissionTime')
def ownedCommentsPreview(self):
return Comment.objects.filter(project=self).order_by('-submissionTime')[0:3]
def ownedVotes(self):
return Vote.objects.filter(project=self,upVoted=True).count()
class Vote:
project=models.ForeignKey(Project)
user=models.ForeignKey(User)
vote=models.IntegerField(...)
class Comment:
project=models.ForeignKey(Project)
user=models.ForeignKey(User)
title=models.CharField(...)
Here are relevant parts of my views.py:
def getCurrentUserData(request=None):
if (request==None) or (request.user.is_authenticated()==False):
return {'loggedInUsername':'Anonym','userIsLoggedIn':False}
return {'loggedInUsername':request.user.username,'userIsLoggedIn':True}
def getProjectResponse(request,surveyFile=None,additionalInfo={}):
userVotedUp=[]
if surveyFile!=None:
userVotes=Vote.objects.filter(upVoted=True,surveyFile=surveyFile)
for vote in userVotes:
userVotedUp.append(vote.project.id)
answerDict={'userVotedUp':userVotedUp,'prjCategories':PrjCategory.objects.select_related(),'projects': Project.objects.prefetch_related('category').filter(visible=True),'spammerquestion':spammerquestion.SpammerQuestion().getRandomQuestion(),'rotatingLines':helpers.getRandomRotatingLines(),'backgroundimageurl':helpers.getBackgroundImageUrl()}
answerDict.update(getCurrentUserData(request))
answerDict.update(additionalInfo)
return answerDict
def showProject(request,prjNo):
currentPrj=get_object_or_404(Project,prjNo=prjNo,visible=True)
surveyFile=assignSurveyFile(request,create_surveyFile_if_not_existing=False)
return render_to_response('website/singleproject.html', getProjectResponse(request,surveyFile,{'currentPrj':currentPrj,'immediateProjectID':currentPrj.id}),context_instance=RequestContext(request))
The template contains many iterations over projects and categories, there might be several database calls happening here. Relevant parts of the template are:
{% for project in projects %}
self.vote['{{ project.id }}']=ko.observable(new Vote({'totalVoteNumber':ko.observable({{ project.ownedVotes }}),'userVoteState':ko.observable({% if project.id in userVotedUp %}true{% else %}false{% endif %})}));
self.comments['{{ project.id }}']=ko.observableArray([]);
{% for comment in project.ownedCommentsPreview %}
self.comments['{{ project.id }}'].push(new Comment({'description':'{{ comment.description|striptags|safe }}','submissionTime':'{{ comment.submissionTime|humanDT }}','commentUuid':'{{ comment.commentUuid }}','deletable':false}));
{% endfor %}
{% endfor %}
{% for prjCat in prjCategories %}
.prjCatUnderline{{ prjCat.id }} {border-bottom: 0px solid {{ prjCat.color }};}
.prjCatUnderline{{ prjCat.id }}:hover {border-bottom: 3px solid {{ prjCat.color }};}
{% endfor %}
{% for prjCat in prjCategories %}
{{ prjCat.title }}
{% if not forloop.last %}<span class="catpipe">|</span>{% endif %}
{% endfor %}
<script type="text/javascript">
var projectLocations = [{% for project in projects %}{% if project.location != '' %}['{{ project.title }}', {{ project.location }}, {{ project.id }}, '{{ MEDIA_URL }}{{ project.mapImage }}', {{ project.mapImage.width }}, {{ project.mapImage.height }}, '{{ project.id }}'],
{% endif %}{% endfor %}];
</script>
{% for project in projects %}
<div class="item prjCat{{ project.category.id }}">
<div class="prjnumberbox">
<div class="numberbar" style="background-color:{{ project.category.color }}"></div>
<div class="prjnumber">{{ project.prjNo|stringformat:"02d" }}</div>
<div class="numberbar" style="background-color: {{ project.category.color }}"></div>
</div>
<div class="prjheadline"><span>{{ project.title }}</span></div>
<div class="prjimagecontainer">
<!-- ko with: $root.vote['{{ project.id }}'] -->
<div class="prjimageoverlay"><a data-bind="click: function(data,event) { $root.showSingleProjectData('{{ project.id }}',data) },css : { imgVoted :userVoteState }" class="singleProjectOverlay" href="{% url 'website.views.showProject' prjNo=project.prjNo %}"></a></div>
<div class="prjimage"><img src="{{ MEDIA_URL }}{{ project.teaserImage }}" /></div>
<!-- /ko -->
</div>
<div class="prjtextcontainer" {% if project.ownedComments|length_is:"0" %}style="background-image:none;"{% endif %}>
<div class="prjtext">{{ project.teaserText|safe }} <a class="singleProjectOverlay" data-bind="click: function(data,event) { showSingleProjectData('{{ project.id }}',data) }" href="{% url 'website.views.showProject' prjNo=project.prjNo %}">mehr >></a></div>
<div class="votesline"><span class="voteslinefont" data-bind="with: vote['{{ project.id }}']"> <span class="votecount" data-bind="text: totalVoteNumber">{{ project.ownedVotes }}</span> votes </span></div>
<div class="prjcomments nojs">
{% for comment in project.ownedCommentsPreview|slice:":4" %}
<div class="prjcommentitem">
{{ comment.teaserdescription }}
</div>
{% endfor %}
</div>
<div class="prjcomments" data-bind="foreach: comments['{{ project.id }}'], visible: comments['{{ project.id }}']().length > 0">
<!-- ko if: $index() < 4 -->
<div class="prjcommentitem">
<em data-bind="text: submissionTime"> </em><br/>
<span data-bind="text: description"> </span>
[X]
</div>
<!-- /ko -->
</div>
</div>
</div>
{% endfor %}
For the front page I'd like to retrieve all the projects, most recent three comments, the total number of votes for a project and the comments and votes by the user.
It would be great if that was possible with one db call, or with two, a general one to get the number of votes and the comments, and one for the data specific to the user.
CUrrently I am retrieving all the projects with one call, so I am automatically getting all the project categories. Then I get all the comments at once and assign them to the projects in python. I then get the comments and votes for a certain user with one call each.
Is there a way - without using sql directly - to get
comments and votes for a user with a single database call
comments, projects, accumulated number of votes per project and project categories at once?
One idea would be to download the whole database using select_related() and then sorting everything out in Python, but if in the future I have a large number of votes or comments, this might not be a good idea.