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')
Related
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>
I'm doing a Django blog website project.
One of my features is when you log in, you can click on the tab Other members to show you a list of other members; like this picture
.
However, as of now, this feature only works when I login as one specific account which is an admin. When I log in as other members (not the admin) or another admin account, the feature is not working; that means when I click the tab Other Members it will display errors like
"Friend matching query does not exist"
I'm really confused and getting stuck on this one. Any ideas how to solve it?
Here is my code:
**list_users.html **
{% extends "blog/base.html" %}
{% block content %}
<div class="container">
<div class="col-sm-6">
<h2>Other People</h2>
{% for user in users %}
<a href="{% url 'view_profile_with_pk' pk=user.pk %}">
<h3>{{ user.username }}</h3>
</a>
{% if not user in friends %}
<a href="{% url 'change_friends' operation='add' pk=user.pk %}">
<button type="button" class="btn btn-success">Add Friend</button>
</a>
{% endif %}
{% endfor %}
</div>
<br>
<div class="col-sm-6">
<h2>Friends</h2>
{% for friend in friends %}
<a href="{% url 'view_profile_with_pk' pk=friend.pk %}">
<h3>{{ friend.username }}</h3>
</a>
<a href="{% url 'change_friends' operation='remove' pk=friend.pk %}">
<button type="button" class="btn btn-default">Remove Friend</button>
</a>
{% endfor %}
</div>
</div>
{% endblock content %}
views.py function listusers
def listusers(request):
posts = Post.objects.all().order_by()
users = User.objects.exclude(id=request.user.id)
friend = Friend.objects.get(current_user=request.user)
friends = friend.users.all()
context = {
'posts': posts, 'users': users, 'friends': friends
}
return render(request, 'blog/list_users.html', context)
model.py class Friend
class Friend(models.Model):
users = models.ManyToManyField(User)
current_user = models.ForeignKey(User, related_name='owner', null=True, on_delete=models.CASCADE)
It's because you are using get operator to get the friend. The problem as the image you provided shows, is in line 25 of your views. in below method:
friend = Friend.objects.get(current_user=request.user)
you are trying to get an item which does not exist. There is no friend that it's current_user is the requested user.
you can fix it like this:
friend = Friend.objects.filter(current_user=request.user).first()
if friend:
friends = friend.users.all()
else:
friends = User.objects.none()
Try to use filter instead of get . get throws exception when there's no matching result.
Have a look at filter
Friend.objects.filter(current_user=request.user).first()
Another approach is to create a Friend instance if a user does not have one. You can use get_or_create for this. For example:
users = User.objects.exclude(id=request.user.id)
friend, created = Friend.objects.get_or_create(current_user=request.user) # or have other necessary fields for Friend field
friends = friend.users.all()
context = {
'posts': posts, 'users': users, 'friends': friends
}
return render(request, 'blog/list_users.html', context)
Nothing is shown in a tag.
I wrote in views.py
def top(request):
content = POST.objects.order_by('-created_at')[:5]
category_content = Category.objects.order_by('-created_at')[:5]
return render(request, 'top.html',{'content':content,'category_content':category_content})
in models.py
class Category(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
in top.html
<ul class="list-group">
<li class="list-group-item active text-center">category</li>
<div class="collapse">
{% for category in category_content %}
<a href="" class="list-group-item">
{{ category.name }}
</a>
{% endfor %}
</div>
</ul>
Now output is like
so category.name is not shown.My ideal output is
I really cannot understand why category.name is not shown.I print out print(category_content) in views.py's top method,so , ]> is shown.How should I fix this?What is wrong in my codes?
Categories are not visible, because you used collapse CSS class in the div, which means it's not displayed.
If you check Bootstrap 4 documentation on collapse, you'll see that it states
.collapse hides content
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.
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?