Django for loop in html template not displaying - python

So I am trying to get the latest post and I ran into a problem where it will not display the post
views.py
def latest_post(request):
latest = Post.objects.all().order_by('-id')[:1]
context = {'latestPost': latest}
return render(request, 'latest_post.html', context)
Note: I also tried it with this, latest = Post.objects.all()
There are entries in the database, I tested with the shell
from blog.models import Post
>>> Post.objects.all()
<QuerySet [<Post: test>, <Post: okay so>, <Post: okay-okay>]>
latest_post.html
{% for newest in latestPost %}
<section class="hero is-primary is-medium">
<div class="hero-body header">
<div class="container">
<div class="font">
<h1 class="title is-1">
<span id="blog_title">{{ newest.title }}</span>
</h1>
<h2 class="subtitle is-3 subup">
<span id="blog-subtitle">{{ newest.content|truncatechars:20|safe }}</span>
</h2>
<h2 class="subtitle is-5 dateup">
<span id="blogdate">{{ newest.timestamp }}</span><br><br>
Read More >>
</h2>
</div>
</div>
</div>
</section>
{% endfor %}
in my blog_index.html I have the following
{% extends "blog_base.html" %}
{% block blog_main %}
{% load staticfiles %}
{% include 'latest_post.html' %}
<p> other html here </p>
{% endblock %}
Latest_post.html displays when i use {% include 'latest_post.html' %} only if I don't use
{% for newest in latestPost %}
{% endfor %}
So i am sure there aren't any typos somewhere that prevents the latest_post.html from displaying in my index page.
my models.py
class Post(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
content = models.TextField()
draft = models.BooleanField(default=False)
publish = models.DateField(auto_now=False, auto_now_add=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __str__(self):
return self.title
def blog_url(self):
return reverse("blogposts:blogdetail", kwargs={"slug": self.slug})
Additional Notes: python3, django 1.11, sqlite.
Also, No errors are displayed in the console. any help would be appreciated! thank you!!

Looks like you are passing context variable to latest_post.html directly:
return render(request, 'latest_post.html', context)
But there is no such context variable latestPost in blog_index.html.
What you need to do is add context to blog_index.html. Add this to index view also:
latest = Post.objects.all().order_by('-id')[:1]
context = {'latestPost': latest}
return render(request, 'blog_index.html', context)
Also you can use first to select first element in queryset.

In your previous code you are limiting it by using [:1] so it only returns one item. Then you are using a forloop again on one item. Not the best way to do things.
Are you trying to get only one item from the post? If yes, Forloop is not needed change your latest_post.html to
<section class="hero is-primary is-medium">
<div class="hero-body header">
<div class="container">
<div class="font">
<h1 class="title is-1">
<span id="blog_title">{{ latestPost.title }}</span>
</h1>
<h2 class="subtitle is-3 subup">
<span id="blog-subtitle">{{ latestPost.content|truncatechars:20|safe }}</span>
</h2>
<h2 class="subtitle is-5 dateup">
<span id="blogdate">{{ latestPost.timestamp }}</span><br><br>
Read More >>
</h2>
</div>
</div>
</div>
</section>
You don't even need to use the [:1] in your views. There are better ways to do this

I also stuck in the same problem and I was damn confirmed that I was doing any silly mistakes.
Unfortunately, I found one. So,
Try this:
context = {'latest': latest}
Instead of:
context = {'latestPost': latest}
I hope it works.

Related

Transferring user input from one page to another

I am making a website that allows students to find upcoming study sessions for their courses. I am doing this in Django and HTML. A student uploads their courses to the site and they are shown on the courses page as buttons (ex. CS 101 - Intro to CS). When a student clicks on one of their courses (button), it is supposed to bring them to a page that shows available study sessions for that course. I am stuck because I do not know how to properly filter the available study sessions on the next page based on which course is clicked. Is there a way to store the info of the course as a variable so when the button is clicked I can use that variable to filter the results? EDIT: I have made these changes and now I am getting a ValueError too many values to unpack expected 2. I am almost certain it is happening in my views.
Here is the page that shows a user's courses:
<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
<div class="row">
{% if courses_list %}
{% for course in courses_list %}
<a type="button" class="btn btn-outline-secondary" href="{% url 'study:course-session'%}" >{{ course.subject }} {{ course.number}}-{{course.name}} </a>
<br><br><br>
{% endfor %}
{% else %}
<p class="text-center">You have not added any courses yet!</p>
{% endif %}
</div>
</div>
And here is the page that I am trying to filter the list of study sessions (which have a field course that is a ForeignKey to the Courses model):
<h1><center>Upcoming Study Sessions</center></h1>
<div>
<a class="btn btn-success" style="position:absolute; margin-right:2px; top:15%; right:0;" href="{% url 'study:courses' %}" role="button" >Back to My Courses</a>
</div>
<br><br>
<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
<div class="row">
<button type="button" class="btn btn-outline-secondary" >Date/Time: {{ session.date }} <br> Location: {{ session.location }} </button>
<br><br><br>
</div>
</div>
View for the template:
def CourseSessionView(request, course_pk):
course_wanted = Course.objects.get(id=course_pk)
try:
return Study.objects.filter(course=course_wanted)
except:
return messages.error(request, 'There are no upcoming study sessions at this time for the requested course.')
Model for course and session:
class Course(models.Model):
SUBJECT_CHOICES = [
('AAS', 'AAS')
]
subject = models.CharField(
max_length=4, choices=SUBJECT_CHOICES, default='')
number = models.PositiveSmallIntegerField(
validators=[MaxValueValidator(9999)], default=0)
name = models.CharField(max_length=100, default='')
roster = models.ManyToManyField(
Student, blank=True, related_name="courses")
# Use [Student object].courses.all() to see all of a student's courses
def __str__(self):
return f"{self.subject} {self.number} - {self.name}"
class Study(models.Model):
organizer = models.ForeignKey(Student, on_delete=models.CASCADE)
date = models.DateTimeField()
# Use [Student object].studies.all() to see all of a student's study sessions
attendees = models.ManyToManyField(Student, related_name="studies")
location = models.CharField(max_length=30)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def __str__(self):
return f"{self.date} - {self.location}"
Url:
path('<int:course_pk>/sessions/',
views.CourseSessionView, name='course-session')
Note: The function based views' name doesn't require to be in PascalCase as in your case, it should be in snake_case.
The page that show the user's courses, there you need to pk of courses:
<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
<div class="row">
{% if courses_list %}
{% for course in courses_list %}
<a type="button" class="btn btn-outline-secondary" href="{% url 'study:course-session' course.pk %}" >{{ course.subject }} {{ course.number}}-{{course.name}} </a>
<br><br><br>
{% endfor %}
{% else %}
<p class="text-center">You have not added any courses yet!</p>
{% endif %}
</div>
</div>
Your view for the template, i am defining it in snake_case, since its recommended way.
def course_session(request, course_pk):
course_wanted = Course.objects.get(id=course_pk)
study_courses=''
try:
study_courses= Study.objects.filter(course=course_wanted)
except:
messages.error(request, 'There are no upcoming study sessions at this time for the requested course.')
else:
return render(request,'anyfolder/anyfile.html',{'study_courses':study_courses})
return render(request,'anyfolder/anyfile.html') #then it will show only your error message.
Your url in urls.py be like:
path('any_route_name/<int:course_pk>/', views.course_session, name='course_session')
Note: Never forget to pass / at the end of your url or route_name.
Then, in your any template file you can access it and run loop:
{% for study in study_courses %}
{{study.organizer}},{{study.date}}
{% endfor %}
Then, you can access all its properties, and take benefit of ManyToOne relation.
This is going to be a very general type of answer since you are not providing your models or your views, but I think the idea would be the following.
First, in your template you can pass a parameter for the course number in the url:
your_template.html
<a class="btn btn-outline-secondary"
href="{% url 'study:course-session' course.pk %}">
{{ course.subject }} {{ course.number}}-{{course.name}}
</a>
Then in your view you can access that value, and from it get the course:
views.py
def the_view_name(request, course_pk):
# Here you now have access to the course's primary key, pk, so you can get the
# course and filter the study sessions by that course, etc...
You will need to modify the urls.py so the view can accept this new parameter:
urls.py
path('the_view_name/<int:course_pk>', views.the_view_name, name='the_view_name'),
EDIT
Make the following changes:
First to your views.py:
def CourseSessionView(request, course_pk):
try:
course_wanted = Course.objects.get(id=course_pk)
except:
return messages.error(request, 'course not found')
study_sessions = Study.objects.filter(course=course_wanted)
if study_sessions.count() < 1:
return messages.error(request, 'There are no upcoming study sessions at this time for the requested course')
context = {
'study_sessions': study_sessions,
}
return render(request, 'study/your_template_file.html', context)
Then in your html
<h1><center>Upcoming Study Sessions</center></h1>
<div>
<a class="btn btn-success" style="position:absolute; margin-right:2px; top:15%; right:0;" href="{% url 'study:courses' %}" role="button" >Back to My Courses</a>
</div>
<br><br>
<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
{% for session in study_sessions %}
<div class="row">
<button type="button" class="btn btn-outline-secondary" >Date/Time: {{ session.date }} <br> Location: {{ session.location }} </button>
<br><br><br>
</div>
{% endfor %}
</div>

how show favorite list in django

I have a list of favorites and I want to show them when I click on the interest button after I click on the list and my heart will be bold. The second part, ie filling the heart, is done correctly, but when I want to show the list, it does not show anything and gives the following error.
Reverse for 'show_Book' not found. 'show_Book' is not a valid view function or pattern name.
model.py
class Book (models.Model):
BookID= models.AutoField(primary_key=True)
Titel=models.CharField(max_length=150 )
Author=models.ForeignKey('Author',on_delete=models.CASCADE)
Publisher=models.ForeignKey('Publisher',on_delete=models.CASCADE) translator=models.ForeignKey('Translator',null='true',blank='true',on_delete=models.SET_NULL)
favorit=models.ManyToManyField('orderapp.Customer',related_name='favorit', blank=True)
view.py
def show_Book(request,BookID):
showBook=get_object_or_404(Book,BookID=BookID)
is_favorite=False
if showBook.favorit.filter(id=request.user.id).exists():
is_favorite=True
return render (request , 'showBook.html', {'is_favorite':is_favorite,})
def favoritbook (request, BookID):
showBook=get_object_or_404(Book,BookID=BookID)
if showBook.favorit.filter(id=request.user.id).exists():
showBook.favorit.remove(request.user)
else:
showBook.favorit.add(request.user)
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
def favoritlist(request):
user=request.user
favoritbooks=user.favorit.all()
context={'favoritbooks':favoritbooks}
return render (request,'favotritlist.html',context)
url.py
path('showbookstor/<int:id>', views.show_BookStor, name='show_BookStor'),
path('books/favorit/<int:BookID>/', views.favoritbook, name='favoritbook'),
path('books/favorit/', views.favoritlist, name='favoritlist'),
showbook.html
{% if is_favorite %}
<li id="sell">add to favorit <i class="fas fa-heart"></i> </li>
{% else %}
<li id="sell"> delete favorit <i class="far fa-heart"></i> </li>
{% endif %}
favoritlist.html
{% for Book in favoritbooks %}
<section id="card" class="col-md-6 col-lg-3 col-sm-6 col-xs-12">
<img src= {{Book.Image.url}}>
<h1 id="bookname">{{Book.Titel}}</h1>
<p>{{Book.Author}}</p>
</section>
{% endfor %}
you use {% url 'show_Book' Book.BookID %} but you don't have any definition in the urls.py with name show_Book try changing
path('showbookstor/<int:id>', views.show_BookStor, name='show_BookStor')
to
path('showbook/<int:id>', views.show_Book, name='show_Book')

Django, link to object in db

I've got a django test-project going with a postgresql db with a table called customers.
Rendering all the customers in /customers/ is fine but I'm looking for a way to render a single customer like this: /customer/{{customer.id}}. Not really sure what I'm looking for, anyone that can guide me to the correct documentation or something?
Much appreciated.
List all customers and open given customer when clicking on the div:
<div class="container">
{% for customerz in custs_all %}
<br>
<div class="row shadow-sm d-flex w-1000 justify-content-between" onclick="location.href='/customers/{{customerz.id}}';" style="cursor: pointer;">
<div class="col-xl-4"><h5 class="mb-1">{{ customerz.name }}</h5></div>
<div class="col-xl-4">Contact person: {{ customerz.contactperson }}</div>
<div class="col-xl-4">Email: {{ customerz.email }}</div>
<div class="col-xl-4">Active: <span class="badge badge-light">{{ customerz.active }}</span></div>
</div>
{% endfor %}
</div>
So this is what I dont understand, what doc do I need to read to setup this to work?
onclick="location.href='/customers/{{customerz.id}}';"
I dont know what I'm looking for, so its hard to ask the right questions here.. Sorry
views.py
def customer_detail(request, pk):
customer = get_object_or_404(Customer, id=pk)
return render (request, template, {'customer': customer}
Here pk is primary key so you are getting a customer from your model Customer(or whatever you have named it).
urls.py
path('customer/<int:pk>/', views.customer_detail, name='customer-detail')
And in cutomer list template you can add link to add you customer detail template like cutomer detail
I think you are looking for this. You can pass an ID in the URL request and use it to get your desired object from the database.
urls.py
path('customer/<int:pk>/', views.customer_detail, name='customer-detail'),
views.py
def customer_detail(request, pk):
customer = Customers.objects.get(id=pk)
return render (request, 'customer.html', {'customer': customer})
customer.html
{% extends "base.html" %}
{% block content %}
<br>
<div class="container row">
<div class="col-xl-12"><h5 class="mb-1">{{ customer.name }}</h5></div>
<div class="col-xl-12">Active: <span class="badge badge-light">{{ customer.active }}</span><hr></div>
<div class="col-xl-12">Description: {{ customer.desc }}<hr></div>
<div class="col-xl-12">Contact person: {{ customer.contactperson }}</div>
<div class="col-xl-12">Email: {{ customer.email }}</div>
<div class="col-xl-12">Address: {{ customer.addr }}</div>
<div class="col-xl-12">Last updated: {{ customer.modified }}</div>
</div>
<br>
{% endblock %}
This is currently doing exactly what i want :)
The previous answer was correct, in action doe ; you could do something like this :
-- you could grab the customer id through request.form; if you use form within your table; i guess this is the best approach to do so.
-- than you can set something with (url_for), and give it a parameter as {{ customer.id}} , within your .html .
-- than handle the logic when returning this object.
You can check this project, go through it , you might find something similar to this :
[https://github.com/Nouamanezh909/BLog_repo][1]

Django template for loop iteration by distinct foreign key

In my app, I have 3 models: Issue, Series, and Character. The Issue model has a Series ForeignKey, and a Character ManyToManyField. Here they are simplified:
class Character(models.Model):
name = models.CharField('Character name', max_length=200)
desc = models.TextField('Description', max_length=500)
class Series(models.Model):
name = models.CharField('Series name', max_length=200)
desc = models.TextField('Description', max_length=500)
class Issue(models.Model):
series = models.ForeignKey(Series, on_delete=models.CASCADE, blank=True)
name = models.CharField('Issue name', max_length=200)
number = models.PositiveSmallIntegerField('Issue number')
date = models.DateField('Cover date')
desc = models.TextField('Description', max_length=500)
characters = models.ManyToManyField(Character, blank=True)
cover = models.FilePathField('Cover file path', path="media/images/covers")
I have a Character template that displays information about the character. I want to also display Issues the Character is in, sorted by Series.
{% extends "app/base.html" %}
{% block page-title %}{{ character.name }}{% endblock page-title %}
{% block content %}
<div class="description">
<p>{{ character.desc }}</p>
</div>
<div class="issues">
<h3>Issues</h3>
{% for series in character.issue_set.all %}
<div>
{{ series.name }}
<ul>
{% for issue in character.issue_set.all %}
{% if issue.series.name == series.name %}
<li>
<img src="/{{ issue.cover }}" alt = "{{ series.name }}" >
<p>Issue #{{ issue.number }}</p>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
{% endblock content %}
Obviously, the way this currently formats is that for every issue in the set, it outputs the series title, and then each issue in the set.
<div class="issues">
<h3>Issues</h3>
<div>
Series 1
<ul>
<li>
<img src="/media/images/covers/01.jpg" alt="Series 1">
<p>Issue #1</p>
</li>
<li>
<img src="/media/images/covers/02.jpg" alt="Series 1">
<p>Issue #2</p>
</li>
</ul>
</div>
<div>
Series 1
<ul>
<li>
<img src="/media/images/covers/01.jpg" alt="Series 1">
<p>Issue #1</p>
</li>
<li>
<img src="/media/images/covers/02.jpg" alt="Series 1">
<p>Issue #2</p>
</li>
</ul>
</div>
</div>
Here's what I would like to see:
<div class="issues">
<h3>Issues</h3>
<div>
Series 1
<ul>
<li>
<img src="/media/images/covers/01.jpg" alt="Series 1">
<p>Issue #1</p>
</li>
<li>
<img src="/media/images/covers/02.jpg" alt="Series 1">
<p>Issue #2</p>
</li>
</ul>
</div>
</div>
I've researched quite a bit on templating, and I'm not seeing a way to get a listing based on distinct values. I've also tried creating a new set in my Character or Issue model that I could use to replace issue_set.all, but I have yet to get it working.
EDIT: Upon request of marcusshep, the Character view is using the generic DetailView:
class CharacterView(generic.DetailView):
model = Character
template_name = 'app/character.html'
I would use a function based view rather than a class based generic view. Reason being that your required behavior is going beyond something generic.
In your function you can build the queryset you desire instead of having to fight with the one provided by generic.DetailView.
def my_view(request, *args, **kwargs):
character = Character.objects.get(id=request.GET.get("id", None))
issues = character.issue_set.all().order_by("series__name")
return render(request, 'app/character.html', {"issues": issues})
Alternatively, you can use what you already have and override the DetailView's get_queryset() method.
class CharacterView(generic.DetailView):
model = Character
template_name = 'app/character.html'
def get_queryset():
# return correct queryset
The biggest problem though is that there will be more aspects that will need to use this set. For instance, I'll be adding Creators, Story Arcs, etc. they will have their own pages and will need to display related issues, sorted by series as well. It would be nice to have a solution that can be used by any of these templates without much code re-use.
This is a very common problem in all areas of programming. A very simple way to solve this would be to isolate the logic in one function and call that function whenever you need it.
def my_issues_query():
# find the objects you need
def my_view(request, *args, **kwargs):
issues = my_issues_query()
You can also take advantage of pythons decorator functions. (Which is my favorite approach.)
def has_issues(view_function):
def get_issues(request, *args, **kwargs):
# find all the issues you need here
# you'll only need to write this logic once.
issues = Issues.objects.filter(...)
return issues
return get_issues
#has_issues
def my_view(request, *args, **kwargs):
# this functions namespace now contains
# the variable `issues`.
# which allows for the use of the query ie.
return render(
request,
"my_templates/template.html",
{"issues":issue}
)

Django Filter Error

I want to save and filter users objects in my django app. After inputting the below codes, the imagefield keeps giving me a validation error, saying:
This field is required.
It’s pointing to the imagefield that I should fill it. How can I get rid of that error and make it filter?
Models
class Fin(models.Model):
user=models.ForeignKey(User)
title=models.CharField(max_length=250)
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
address=models.CharField(max_length=200)
city=models.CharField(max_length=200)
state=models.CharField(max_length=200)
guideline=models.TextField(max_length=1000)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return self.title
class FinForm(ModelForm):
class Meta:
model=Fin
fields=('title','main_view','side_view', 'address','city','state','guideline')
exclude=('user')
Views
def fincrib(request):
extra_data_context={}
#if there's nothing in the field do nothing.
if request. method=="POST":
form =FinForm(request.POST)
if form.is_valid():
data=form.cleaned_data
newfincribs=Fin(
user= request.user,
title=data['title'],
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
address=data['address'],
city=data['city'],
state=data['state'],
guideline=data['guideline'])
newfincribs.save()
extra_data_context.update({'FinForm':form})
else:
form = FinForm()
extra_data_context.update({'FinForm':form})
extra_data_context.update({'Fins':Fin.objects.filter(user=request.user)})
plan=Fin.objects.filter(user=request.user)
paginator=Paginator(plan, 5)
try:
page=request.GET.get('page', '1')
except ValueError:
page=1
try:
Fins=paginator.page(page)
except (EmptyPage, InvalidPage):
Fins=paginator.page(paginator.num_pages)
extra_data_context.update({'Fins': Fins})
return render_to_response('post.html',extra_data_context,context_instance=RequestContext(request))
Template
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<center> {{FinForm.as_p}} </center>
<input type="submit" value="Submit"/>
</form>
{% for Fin in Fins.object_list %}
<tr>
{{Fin.user}} </p> </strong>
<p>{{Fin.title}}</p>
<p><img src="{{MEDIA_URL}}/{{Fin.main_view}}"/></p>
<p> <img src="{{MEDIA_URL}}/{{Fin.side_view}}"/></p>
<p> {{Fin.address}} </p>
<p> {{Fin.city}}</p>
<p> {{Fin.state}}</p>
<p> {{Fin.guideline}}</p>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if Fins.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ Fins.number }} of {{ Fins.paginator.num_pages }}
</span>
{% if Fins.has_next %}
next
{% endif %}
</span>
</div>
{% endblock %}
It's because by default all model fields are required, it means if you want to create and save new model instance in the database, you should fill all the mandatory fields. Maybe
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
is giving you the error, because there is no data.
change
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
to
main_view=models.ImageField(upload_to="photos", blank=True, null=True)
side_view=models.ImageField(upload_to="photos", blank=True, null=True)
btw, im not sure which django version you're using but your code is rather messy, any reason you're not using CBVs and static tags?

Categories

Resources