How to capture values in checked checkboxes using Django - python

I am creating a web application that will serve as a grocery store. The way I set it up is so the customer can come onto the website, click on the items that they would like to purchase, and then click a submit button to purchase those items. The problem I am running into is having a views.py function to take the information of which products were selected and subtracting 1 from the quantity of the database. When I say print(products) in my views.py, it returns "[]" in my terminal. This means that the values in my checked checkboxes are not being captured. Can anyone help me solve this?
"""models.py"""
class Post(models.Model):
title = models.CharField(max_length=100)
Price = models.DecimalField(max_digits=4, decimal_places=2,default=1)
Sale = models.DecimalField(max_digits=4, decimal_places=2,default=1)
quantity = models.IntegerField(default=1)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = TreeForeignKey('Category',null=True,blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
views.py
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
def inventory(request):
products = request.POST.getlist('products')
a = Post.objects.filter(title=products).update(
quantity=F('quantity')-1
)
return redirect('blog-home')
urls.py
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('inventory', views.inventory, name='inventory'),
home.html
{% extends "blog/base.html" %}
{% block content %}
{% for post in posts %}
{% if post.quantity > 0 %}
<input type="checkbox" name="products" id="product_{{ post.id }}" value="{{ post.id }}">
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.category }}</a>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content"> Price: ${{ post.Price }}</p>
<p class="article-content"> Sale: ${{ post.Sale }}</p>
Inventory count: {{ post.quantity }}
</input>
</div>
</article>
{% else %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.category }}</a>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content"> Price: ${{ post.Price }}</p>
<p class="article-content"> Sale: ${{ post.Sale }}</p>
Inventory count: {{ post.quantity }}
<p>Out Of Stock!</p>
</div>
</article>
{% endif %}
{% endfor %}
<button type="submit" name="Purchase" >Confirm Purchase</button>
{% endblock content %}
My goal is to click on the checkboxes, and when the customer clicks the button on the bottom of home.html, it triggers the inventory function to subtract "1" from the quantity.

You have to create a form in your HTML to handle this POST request.
Then handle this in your view with if request.method == 'POST' followed by the getlist() and the update function. also, i think you need to add a for loop to your queryset because there could be more than one product. hope this helps!
def inventory(request):
if request.method == 'POST':
products = request.POST.getlist('products')
for product in products:
a = Post.objects.filter(title=product).update(
quantity=F('quantity')-1
)
return redirect('blog-home')

Related

How to go to a page with single post from the news list

Can you help me with my project.
I 'm trying to go from the page with all the news to a single post, but whatever i stay in page with all news.
But if I write the address o in the address bar, everything works.
Models.py
class News(models.Model):
title = models.CharField(max_length=1000, verbose_name='Название')
slug = models.SlugField(max_length=200, db_index=True)
image = models.ImageField(upload_to='articles/', verbose_name='Фото')
publish = models.DateTimeField(default=timezone.now, verbose_name='Дата публикации')
author = models.ForeignKey(User, related_name='news', on_delete=models.CASCADE, verbose_name='Автор', null=True)
text = models.TextField(verbose_name='Текст')
tags = models.ManyToManyField(Tag, related_name='news', verbose_name='Тэг')
created = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
updated = models.DateTimeField(auto_now=True, verbose_name='Дата обнавления')
status = models.CharField(max_length=30, choices=STATUS_CHOICES, default='опубликован', verbose_name='Статус')
class Meta:
ordering = ('title',)
verbose_name = 'Новости'
verbose_name_plural = 'Новости'
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post', kwargs={'post_slug': self.slug})
Views.py
def list_news(request):
news = News.objects.all()
return render(request,
'diplom/news/post.html',
{'news': news})
def single_news(request, post_slug):
post = get_object_or_404(News, slug=post_slug)
return render(request,
'diplom/news/blog-single.html',
{'post': post})
urls.py
urlpatterns = [
path('news/', views.list_news, name='News'),
path('post/<slug:post_slug>/', views.single_news, name='post')
]
templates
<div class="col-lg-4 col-md-6 grid-item">
{% for news in news %}
<div class="blog-item large-item set-bg">{{ news.image }}
<a href="{{post.get_absolute_url}}" methods="post" >
<div class="categories">{{ news.title }}</div>
<h5>{{ news.text| linebreaks|truncatechars:200 }}</h5>
</a>
<div>
{{ news.publish }}
{{ news.tag }}
</div>
</div>
{%endfor%}
</div>
I use the {% url 'url-name' param1 %} for my templates. Does this work when you use it in your template?
URL Reversing
<div class="col-lg-4 col-md-6 grid-item">
{% for post in news %}
<div class="blog-item large-item set-bg">{{ post.image }}
<a href="{% url 'post' post.slug %}">
<div class="categories">{{ post.title }}</div>
<h5>{{ post.text|linebreaks|truncatechars:200 }}</h5>
</a>
<div>
{{ post.publish }}
{{ post.tag }}
</div>
</div>
{%endfor%}
</div>
Also see the name of your single object is the same as your list of objects.
{% for news in news %}
You could rename to post, then change the rest of the variables (not the link) and it should work.
<div class="col-lg-4 col-md-6 grid-item">
{% for post in news %}
<div class="blog-item large-item set-bg">{{ post.image }}
<a href="{{ post.get_absolute_url }}">
<div class="categories">{{ post.title }}</div>
<h5>{{ post.text|linebreaks|truncatechars:200 }}</h5>
</a>
<div>
{{ post.publish }}
{{ post.tag }}
</div>
</div>
{%endfor%}
</div>
</div>
I also updated
<a href="{% url 'post' news.slug %}" methods="post" >
to
<a href="{% url 'post' news.slug %}">
as you are just retrieving the object and not sending information to update it.
Thanks for the answers. The error was in this line.
<a href="{{ post.get_absolute_url }}">
It was necessary to do this
<a href="{{news.get_absolute_url }}">

How to use conditional on Django template?

Im working on my django project. The home page of my project is to show all of my post and category-based post on the bottom after the first part. But my code isnt working and i dont know why. Please help me, im a django noob
#the word Opini is one of my post category
{% for post in blog_posts %}
<div class="card d-inline-flex m-1" style="width: 18rem;">
<a href="{% url 'post-detail' post.pk %}" >
<img class="card-img-top postimg" src="{{ post.post_img.url }}" alt="Card image cap">
</a>
<h3>{{post.category}}</h3>
<div class="card-body">
<h5 class="card-text text-center">{{ post.post_title }}</h5>
<p class="card-text">{{post.post_content|truncatechars:75|safe }}</p>
</div>
</div>
{% endfor %}
<h1> Opini </h1>
{% for post in blog_posts %}
{% if post.category == "Opini" %}
<div class="card d-inline-flex m-1" style="width: 18rem;">
<a href="{% url 'post-detail' post.pk %}" >
<img class="card-img-top postimg" src="{{ post.post_img.url }}" alt="Card image cap">
</a>
<h3>{{post.category}}</h3>
<div class="card-body">
<h5 class="card-text text-center">{{ post.post_title }}</h5>
<p class="card-text">{{post.post_content|truncatechars:75|safe }}</p>
</div>
</div>
{% endif %}
{% endfor %}
{% endfor %}
My Models
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('post_by_category', args=[self.name])
class Post(models.Model):
post_title = models.CharField(max_length=50)
post_img = models.ImageField(upload_to='postImage/')
post_content = RichTextField(blank= True, null = True)
category = models.ForeignKey(Category , on_delete=models.CASCADE)
post_date = models.DateTimeField(auto_now_add=True)
post_author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ["-post_date"]
def __str__(self):
return f'{self.post_title}'
When i run the code, only the first page works, when it comes to the second part, nothing appeared
If "Opini" is the category name then you should compare it like this:
{% if post.category.name == "Opini" %}

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 %}

Display user's posts in their profile on django

I have been trying to make the profile page of a user have the user's posts but everytime I run my code nothing shows up only the user's username and user's email. I've tried multiple ways to make it work but somehow it doesn't. I think the profile.html has the error in it.
views.py
def profile(request, pk=None):
if pk:
post_owner = get_object_or_404(User, pk=pk)
user_posts=Post.objects.filter(posti=request.user)
else:
post_owner = request.user
user_posts=Post.objects.filter(posti=request.user)
return render(request, 'profile.html', {'post_owner': post_owner, 'user_posts': user_posts})
models.py
class Post(models.Model):
text = models.CharField(max_length=200)
posti = models.ImageField(upload_to='media/images', null=True, blank="True")
user = models.ForeignKey(User, related_name='imageuser', on_delete=models.CASCADE, default=2)
profile.html
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ post_owner.username }}</h2>
<p class="text-secondary">{{ post_owner.email }}</p>
</div>
{% for Post in user_posts %}
<li class="list-group-item">{{ Post.text }}
{{ Post.user }}
{% if Post.posti %}
<img src="{{ image.posti.url }}" alt="image here" style="max-width: 300px; max-height: 300px">
{% endif %}
{% if Post.user == user %}
<div class="float-right">
<form action="delete_image/{{ image.id }}/" action="post">
<button type="submit" class="btn btn-outline-danger btn-sm">Delete</button>
</form>
</div>
{% endif %}
</li>
{% endfor %}
</div>
</div>
The problem here is with the line:
user_posts=Post.objects.filter(posti=request.user)
To get the posts from the logged in user you will need to use this:
user_posts=Post.objects.filter(user=request.user)
and to get the posts from the selected user you will need to do this:
user_posts=Post.objects.filter(user_id=pk)
I hope this helps :)
You are querying the wrong column:
user_posts=Post.objects.filter(posti=request.user)
posti is an ImageField. You actually want to query the user field:
user_posts=Post.objects.filter(user=request.user)
That being said, you don't need any of these queries in your view. You can simply make use of your related_name, i.e.:
{% for Post in post_owner.imageuser.all %}

How to add extra category field in django.views.generic

I have class in views.py:
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content',]
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
I want to add object to fields, but when I'm trying to add like this:
fields = ['title', 'content', 'category']
the debugger send an error log like this:
FieldError at /post/new/
Unknown field(s) (category) specified for Post
I need an extra column to add category field when creating post in my django blog.
Here is blog_category.html
{% extends 'blog/base.html' %}
{% block content %}
<h1 class='mb-3'>Category: {{ category | title }}</h1>
{% for post in posts %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}" alt="">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2 author_title" href="{% url 'user-posts' post.author.username %}">#{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"N d, Y" }}</small>
<div>
<small class="text-muted">
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blog_category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</small>
</div>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content|slice:200 }}...</p>
</div>
</article>
{% endfor %}
{% endblock content %}
models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
categories = models.ManyToManyField('Category', related_name='posts')
image = models.ImageField(upload_to='images', default="images/None/no-img.jpg")
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Category(models.Model):
name = models.CharField(max_length=20)
My post_form.html:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Blog Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
The main goal is:
create category field in views.py -> after pressing "Post" this field should push the content to the django admin panel and add category to the post(as title and content adding).
If someone have a ready solution or know how to solve this problem, I would be really happy.
fields = ['title', 'content', 'categories']

Categories