How to loop though user objects in django - python

I want to show all the user's Items.
Currently I can only show 1 object
my_items.html (where i want it to show)
{% extends 'base.html' %}
{% block content%}
<main role="main">
<div class="container">
<!-- Example row of columns -->
<div class="row">
{% for item in item %}
<!--{% if item.id == request.user.id %}-->
<div class="col-md-4">
<div class="col-md-4">
<img style="max-width: 100px; max-height: 300px" src="{{ item.thumb.url }}">
</div>
<h2>{{ item.name }}</h2>
<p>{{ item.snippet }}</p>
<p>{{ item.date }}</p>
<p><a class="btn btn-warning" href="#" role="button">Edit</button></a></p>
<p><a class="btn btn-danger" href="#" role="button">Delete</a></p>
</div>
<!--{% endif %}-->
{% endfor %}
</div>
<hr>
</div> <!-- /container -->
</main>
{% endblock %}
views.py
def item_myitems(request):
item = Item.objects.all().order_by('date')
return render(request, 'items/my_items.html', {'item': item})
I tried using filter() and get() on views.py

You should use a plural name to pass your items to your view:
def item_myitems(request):
items = Item.objects.all().order_by('date')
return render(request, 'items/my_items.html', {'items': items})
So you can distinguish one item from many items when you loop through them in your view:
{% for item in items %}

omg I got it working, i feel so dumb right now LOL
I uncommented my if in the html and set to this > {% if item.author_id == request.user.id %} i was comparing with the item id instead of the author_id

Related

improperly configured at /18/delete, Django views issue

I have searched through the other questions similar to my own problem and have come to no solution so im hoping someone can help me figure out where i went wrong.
I'm trying to implement a delete post option in my blog program but it is throwing the following error once you click the 'delete' button:
ImproperlyConfigured at /18/delete/
Deletepost is missing a QuerySet. Define Deletepost.model, Deletepost.queryset, or override Deletepost.get_queryset().
I am nearly sure its a problem with my URLS.py though what exactly i cannot figure out.
the following is the code in question:
Views.py
# delete post
class Deletepost(LoginRequiredMixin, DeleteView):
form_class = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
urls.py
urlpatterns = [
# home
path('', views.postslist.as_view(), name='home'),
# add post
path('blog_post/', views.PostCreateView.as_view(), name='blog_post'),
# posts/comments
path('<slug:slug>/', views.postdetail.as_view(), name='post_detail'),
# edit post
path('<slug:slug>/edit/', views.Editpost.as_view(), name='edit_post'),
# delete post
path('<int:pk>/delete/', views.Deletepost.as_view(), name='delete_post'),
# likes
path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'),
]
post.html
{% extends 'base.html' %} {% block content %}
{% load crispy_forms_tags %}
<div class="masthead">
<div class="container">
<div class="row g-0">
<div class="col-md-6 masthead-text">
<!-- Post title goes in these h1 tags -->
<h1 class="post-title text-success">{{ post.title }}</h1>
<!-- Post author goes before the | the post's created date goes after -->
<p class="post-subtitle text-success">{{ post.author }} | {{ post.created_on }}</p>
</div>
<div class="d-none d-md-block col-md-6 masthead-image">
<!-- The featured image URL goes in the src attribute -->
{% if "placeholder" in post.featured_image.url %}
<img src="https://codeinstitute.s3.amazonaws.com/fullstack/blog/default.jpg" width="100%">
{% else %}
<img src=" {{ post.featured_image.url }}" width="100%">
{% endif %}
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col card mb-4 mt-3 left top">
<div class="card-body text-dark">
<!-- The post content goes inside the card-text. -->
<!-- Use the | safe filter inside the template tags -->
<p class="card-text text-dark">
{{ post.content | safe }}
</p>
<div class="row">
<div class="col-1">
<strong>
{% if user.is_authenticated %}
<form class="d-inline" action="{% url 'post_like' post.slug %}" method="POST">
{% csrf_token %}
{% if liked %}
<button type="submit" name="blogpost_id" value="{{post.slug}}" class="btn-like"><i class="fas fa-heart"></i></button>
{% else %}
<button type="submit" name="blogpost_id" value="{{post.slug}}" class="btn-like"><i class="far fa-heart"></i></button>
{% endif %}
</form>
{% else %}
<span class="text-secondary"><i class="far fa-heart"></i></span>
{% endif %}
<!-- The number of likes goes before the closing strong tag -->
<span class="text-secondary">{{ post.number_of_likes }} </span>
</strong>
</div>
<div class="col-1">
{% with comments.count as total_comments %}
<strong class="text-dark"><i class="far fa-comments"></i>
<!-- Our total_comments variable goes before the closing strong tag -->
{{ total_comments }}</strong>
{% endwith %}
</div>
<div class="col-1">
<a class="btn btn-outline-danger" href="{% url 'delete_post' post.id %}">Delete It</a>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<hr>
</div>
</div>
<div class="row">
<div class="col-md-8 card mb-4 mt-3 ">
<h3 class="text-dark">Comments:</h3>
<div class="card-body">
<!-- We want a for loop inside the empty control tags to iterate through each comment in comments -->
{% for comment in comments %}
<div class="comments text-dark" style="padding: 10px;">
<p class="font-weight-bold">
<!-- The commenter's name goes here. Check the model if you're not sure what that is -->
{{ comment.name }}
<span class=" text-muted font-weight-normal">
<!-- The comment's created date goes here -->
{{ comment.created_on }}
</span> wrote:
</p>
<!-- The body of the comment goes before the | -->
{{ comment.body | linebreaks }}
</div>
<!-- Our for loop ends here -->
{% endfor %}
</div>
</div>
<div class="col-md-4 card mb-4 mt-3 ">
<div class="card-body">
<!-- For later -->
{% if commented %}
<div class="alert alert-success" role="alert">
Your comment is awaiting approval
</div>
{% else %}
{% if user.is_authenticated %}
<h3 class="text-dark">Leave a comment:</h3>
<p class="text-dark">Posting as: {{ user.username }}</p>
<form class="text-dark" method="post" style="margin-top: 1.3em;">
{{ comment_form | crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-signup btn-lg">Submit</button>
</form>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}
Any ideas?
I think it should be model not form_class so:
class Deletepost(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
#SunderamDubey's answer is correct. The test_func will however not run, since this is method of the UserPassesTestMixin [Django-doc], not LoginRequiredMixin.
But using a test function as is done here is not efficient: it will fetch the same object twice from the database. You can simply restrict the queryset, like:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.views.generic import DeleteView
class DeletePostView(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy('blog:home')
template_name = 'templates/post.html'
def get_queryset(self, *args, **kwargs):
return (
super().get_queryset(*args, **kwargs).filter(author=self.request.user)
)
This will do filtering at the database side, and thus return a 404 in case the logged in user is not the author of the Post object you want to delete.
In the template, you will need to make a mini-form to make a POST request, for example:
<form method="post" action="{% url 'delete_post' post.id %}">
{% csrf_token %}
<button class="btn btn-outline-danger" type="submit">Delete</button>
</form>
In my opinion, you should change url to below
'path('delete/int:pk', views.Deletepost.as_view(), name='delete_post'),'
if didn't work you can do this
def delete_post(request, post_id):
post = Post.objects.get(pk=post_id)
post.delete()
return redirect('blog:home')

Django pagination not working. Object list is rendering items but not dividing into pages

I'm currently working on an e-commerce site and I'm trying to create a product list page that spans into another page after 4 items have been displayed. rendering the page doesn't produce any error but all items in the database are displayed on the same page and remains the same even after switching to another page.
Here's my views.py:
from django.shortcuts import render, get_object_or_404
from .models import Category, Item
from django.core.paginator import Paginator
def item_list(request, category_slug=None):
category = None
categories = Category.objects.all()
items = Item.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
items = items.filter(category=category)
paginator = Paginator(items, 4)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request,
'item/list.html',
{'category': category,
'categories': categories,
'page_obj': page_obj,
'items': items})
my urls.py file:
from django.urls import path
from . import views
app_name = 'shop'
urlpatterns = [
path('', views.item_list, name='item_list'),
path('<slug:category_slug>/', views.item_list, name='item_list'),
path('<int:id>/<slug:slug>/', views.item_detail, name='item_detail'),
]
pagination snippet from the template
<nav class="d-flex justify-content-center wow fadeIn">
<ul class="pagination pg-blue">
<!--Arrow left-->
{% if page_obj.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
Next
{% endif %}
</ul>
</nav>
and the logic that displays the products
<div class="row wow fadeIn">
<!--Grid column-->
{% for item in items %}
<div class="col-lg-3 col-md-6 mb-4">
<!--Card-->
<div class="card" style="width: 16rem; height: 25rem">
<!--Card image-->
<div class="view overlay">
<a href="{{ item.get_absolute_url }}">
{% if item.tags and item.label %}
<div class="imgHolder">
<img src="{{ item.image.url }}" class="img-fluid">
<span class="badge badge-pill {{ item.get_label_display }}-color">{{ item.tags }}</span>
</div>
{% else %}
<img src="{{ item.image.url }}" class="img-fluid">
{% endif %}
</a>
<a href="{{ item.get_absolute_url }}">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!--Card image-->
<!--Card content-->
<div class="card-body text-center" style="height: 9rem;">
<!--Category & Title-->
<a href="{{ item.category.get_absolute_url }}" class="grey-text">
<h5>{{ item.category.name|truncatechars:20 }}</h5>
</a>
<h5>
<strong style="color:red">
{{ item.name }}
</strong>
</h5>
<h6 class="font-weight-bold">
{% if item.discount_price %}
<strong><del>${{ item.price}}</del></strong>
<strong>${{ item.discount_price }}</strong>
{% else %}
<strong>${{ item.price }}</strong>
{% endif %}
</h6>
</div>
<!--Card content-->
</div>
<!--Card-->
</div>
{% endfor %}
</div>
I'd really like to know what I'm doing wrong and I'm also open to alternative means of solving the same problem. Thanks
You are using all the queryset that you are passing to the paginator. You must iterate over the page_obj.object_list.
page_obj = paginator.get_page(page_number)
page_obj_items = page_obj.object_list
you need to loop throw {% for item in page_obj %}

How to change the button based on the user input?

I am implementing a pypi package called django-shopping-card https://pypi.org/project/django-shopping-cart/, so the users can see their saved posts.
My issue is that I could not make the button to display "Remove Post" instead of "Add to Card", if the post was added already. I have tried to create a different method to pass the posts which have been saved, but that caused a an error, as I cannot access the key and values of the cart without for loop. I am new to this and I would highly appreciate any comments and suggestions.
def add_fav(request, id):
cart = Cart(request)
post = Auction.objects.get(id=id)
cart.add(product=post)
return redirect("watchlist")
def item_clear(request, id):
cart = Cart(request)
product = Auction.objects.get(id=id)
cart.remove(product)
return redirect("watchlist")
def items_clear(request):
cart = Cart(request)
cart.clear()
return redirect("watchlist")
def get_cart(request):
return render(request, 'auctions/watchlist.html', {'cart': Cart(request)})
listings.html
{% block body %}
{% for auction in object_list %}
<div class="col-md-4">
<div class="card mb-2">
<div class="card-body">
<h5 class="card-title">{{ auction.name }}</h5>
Price: {{ auction.price }}<br>
<p class="card-text">{{ auction.description|slice:":10" }} ...</p>
{{ auction.author }}
Category: {{ auction.category }}
<hr><img class="card-img-top" src="{{ auction.image.url }}" alt="no" ><br>
{% for key,value in request.session.cart.items|slice:1 %} <br>
{% if value.product_id == auction.id %}
- Delete
{% endif %}
{% endfor %}
<a class="btn btn-primary" id="add_card" href="{% url 'add_fav' auction.id %}"
style="margin-top: 10px; ">Add to card</a><br>
</div>
{{ text }}
</div>
</div>
{% endfor %}
{% endblock %}

How to post data from google books API to your Book model using Django

I know this is my first question and I wouldn't be like writing it here, but I have a problem which I couldn't handle for 2 days now.
I am writing an app in Django, and my goal is to handle requests from google books API and display books in the template which I did.
I wrote a function like this
services.py
from googleapiclient.discovery import build
import json
def get_books_data(query):
"""Retriving data from google books API"""
service = build('books',
'v1',
developerKey=API_KEY
)
request = service.volumes().list(q=query)
response = request.execute()
book_list = [response['items'][item]['volumeInfo']
for item in range(len(response['items']))]
return book_list
I get a list of key: value pairs representing ten books from API.
I passed them into a template like this
views.py
def search(request):
query = request.GET.get('q')
books = get_books_data(query)
context = {
'books': books
}
return render(request, 'books_list.html', context)
This is how book_list.html looks like.
list_book.html
{% extends 'base.html' %}
{% load static %}
{% block content%}
{% for book in books %}
<div class="row">
<div class="col-lg-8 mx-auto">
<ul class="list-group shadow">
<li class="list-group-item">
<div class="media align-items-lg-center flex-column flex-lg-row p-3">
<div class="media-body order-2 order-lg-1">
<h5 class="mt-0 font-weight-bold mb-2">{{ book.title }}</h5>
<p class="font-italic text-muted mb-0 small">{{ book.subtitle }}</p>
{% for identifier in book.industryIdentifiers %}
<p class="font-italic text-muted mb-0 small">{{ identifier.type }} : {{ identifier.identifier }}</p>
{% endfor %}
<p class="font-italic text-muted mb-0 small">Language: {{ book.language }}</p>
<p class="font-italic text-muted mb-0 small">Published date: {{ book.publishedDate }}</p>
<div class="media-body order-2 order-lg-1">
{% if book.authors %}
<h6 class="font-weight-bold my-2">Authors:</h6>
{% for author in book.authors %}
<p class="font-italic text-muted mb-0 small">{{ author }}</p>
{% endfor %}
{% endif %}
</div>
{% if book.pageCount %}
<div class="d-flex align-items-center justify-content-between mt-1">
<h6 class="font-weight-bold my-2">Number of pages: {{book.pageCount}}</h6>
</div>
{% endif %}
</div>
{% if book.imageLinks %}
<img class="thumbnail" src="{{book.imageLinks.thumbnail}}" alt="">
{% else %}
<img class="thumbnail2" src="{% static 'images/placeholder4.png'%}" alt="">
{% endif %}
</div>
<form action="." method="post">
{% csrf_token %}
<button type="submit" class="btn btn-primary">ADD THIS BOOK TO YOUR BOOKSHELF</button>
</form>
</li>
</ul>
</div>
</div>
{% endfor %}
{% endblock content %}
And last part of my task is to have a button in each card with a book, I can use to save a particular book from API to the database.
I am a beginner in Django, and I've tried to use forms, I've read, I could use Django Rest Framework somehow but really, I don't have an idea, how I could approach this problem.
Please, Can you help me?
Than you in advance.

i am getting an error saying category matching query does not exist

The voting proceess is working fine with this code. The problem is only when redirecting after voting the options.
Exception Type:DoesNotExist
Exception Value:
Category matching query does not exist.
category = Category.objects.get(slug=slug)
urls.py
path('<slug>/',views.options,name='options'),
path('<slug>/vote/', views.vote, name='vote'),
views.py
def home(request):
categories = Category.objects.filter(active=True)
return render(request,'rank/base.html',{'categories': categories,'title':'TheRanker'})
def options(request,slug):
category = Category.objects.get(slug=slug)
options = Option.objects.filter(category=category)
return render(request,'rank/options.html',{'options':options,'title':'options'})
def vote(request,slug):
option = Option.objects.get(slug=slug)
if Vote.objects.filter(slug=slug,voter_id=request.user.id).exists():
messages.error(request,'You Already Voted!')
return redirect('rank:options',slug)
else:
option.votes += 1
option.save()
voter = Vote(voter=request.user,option=option)
voter.save()
messages.success(request,'Voted!')
return redirect('rank:options',slug)
options.html
{% extends "rank/base.html" %}
<title>{% block title %}{{title}}{% endblock title%}</title>
{% load bootstrap4 %}
{% block content %}
<center><br>
<center>{% bootstrap_messages %}</center>
<ol type="1">
{% for option in options %}
<div class="col-lg-6 col-md-6 mb-6">
<div class="card h-100">
<div class="card-body">
<b><li>
<img src="/media/{{option.image}}" width="200" height="100">
<h4>{{option.name}}
</h4>
<h5 class="card-text">{{ option.details}}</h5>
<h5>{{ option.votes }} votes</h5>
<form action="{% url 'rank:vote' option.slug %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-success" value="Vote" >
</form>
</li></b>
</div>
<div class="card-footer">
<small class="text-muted"></small>
</div>
</div>
</div>
{% endfor %}
</ol>
</center>
{% endblock content%}
You're confusing categories and options. The form sends the slug of the option, but then you redirect to the categories view using the same slug. But those are two different models.

Categories