Detail view context - python

how can i get all images of item into context
i tried {% for image in item.images.all %} in template but it doesn't work.
i dunno how to filter it , ty for ur answer
models
class Item(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, blank=True)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE, null=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='photos/%Y/%m/%d/', null=True)
size = ArrayField(models.CharField(max_length=255))
price = models.PositiveIntegerField()
on_sale = models.BooleanField(default=0)
discount = models.PositiveIntegerField(null=True, blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('single_product', kwargs={'slug': self.slug})
def get_sale(self):
price = int(self.price * (100 - self.discount) / 100)
return price
class ItemImage(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True, related_name='images')
images = models.ImageField(upload_to='photos/%Y/%m/%d/', null=True)
def __str__(self):
return self.item.name
views
class ItemDetail(DetailView):
model = Item
context_object_name = 'item'
template_name = 'essense/single-product-details.html'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)

You're pretty close. In your template tag {% for image in item.images.all %}, image refers to an instance of your ItemImage model. You need to reference the ImageField within that model, which you've named images. So, instead of
src="{{ image.url }}" use src="{{ image.images.url }}"
<div className="single_product_thumb clearfix">
<div className="product_thumbnail_slides owl-carousel">
{% for image in item.images.all %} <img
src="{{ image.images.url }}" alt="" width="360" height="539">
{% endfor %}
</div>
</div>```

Related

How to add multiply photos to one website page with django?

I'm writing django project for Internet Shop. On the page which describes product I have several photos for this product and I cannot add it to the template. I use 2 models with Many to many relationship - for product and for photos, and added they to template.html. But I don't see any photo in the page. My code is below:
models.py:
class ProductPhoto(models.Model):
def get_file_name(self, filename: str) -> str:
ext_file = filename.strip().split('.')[-1]
new_filename = f'{uuid.uuid4()}.{ext_file}'
return os.path.join('product_photo/', new_filename)
# product = models.ForeignKey(Product, on_delete=models.CASCADE)
photo = models.ImageField(upload_to=get_file_name)
description = models.CharField(max_length=20, blank=True)
def __str__(self):
return f'{self.description}'
class Product(models.Model):
slug = models.SlugField(max_length=200, db_index=True)
title = models.CharField(unique=True, max_length=100, db_index=True)
description_short = models.CharField(max_length=200)
description = models.CharField(max_length=500)
color = models.CharField(max_length=20)
price = models.DecimalField(max_digits=8, decimal_places=2)
sale = models.SmallIntegerField(max_length=2, blank=True)
new_arrival = models.BooleanField(default=True)
is_visible = models.BooleanField(default=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
photo = models.ManyToManyField(ProductPhoto)
def __str__(self):
return f'{self.title}'
class Meta:
index_together = (('id', 'slug'), )
def get_absolute_url(self):
return reverse("shop:products", args=[self.id, self.slug])
views.py:
def product_details(request, id, slug):
product = get_object_or_404(Product, id=id, slug=slug, is_visible=True)
cart = Cart(request)
return render(request,
'single-product.html',
{'product': product,
'cart': cart,
})
template.html:
<div class="product-details-left">
<div class="product-details-images">
{% for item in product.photo.all %}
<div class="lg-image">
<img src="{{ item }}" alt="">
<i class="fa fa-expand"></i>
</div>
{% endfor %}
</div>
<div class="product-details-thumbs">
{% for item in product.photo.all %}
<div class="sm-image"><img src="{{ item }}" alt="product image thumb"></div>
{% endfor %}
</div>
</div>
If I add "print(product.photo)" to "def product_details" in terminal I see:
Not Found: /shop/2/nabir-dlya-vannoyi-vislanda-3od-asort/набір для ванної 2, where "/shop/2/nabir-dlya-vannoyi-vislanda-3od-asort" is absolute_url and "набір для ванної 2" is description which added to photo.
I think it's because of path to photo in "def get_file_name", but I can mistake.
Who nows how to add photos to html template in this case?

filtering reviews according to product django

I want my reviews that are on that particular product to be shown only on that product not on any other . I do not know how to filter it. Recently it is showing all the reviews on every product.
My models.py file is:
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product , on_delete=models.CASCADE, null=True)
date = models.DateTimeField(auto_now_add=True)
text = models.TextField(max_length=3000 , blank=True)
rate = models.PositiveSmallIntegerField(choices=RATE_CHOICES)
likes= models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.user.full_name
my product models.py is:
class Product(models.Model):
title = models.CharField(max_length=110)
slug = models.SlugField(blank=True, unique=True)
status = models.CharField(choices=CATEGORY_CHOICES, max_length=10)
price = models.DecimalField(decimal_places=2, max_digits=6)
quantity=models.IntegerField(default=1)
discount_price=models.FloatField(blank=True, null=True)
size = models.CharField(choices=SIZE_CHOICES, max_length=20)
color = models.CharField(max_length=20, blank=True, null=True)
image = models.ImageField(upload_to=upload_image_path)
description = RichTextField(max_length=1000)
featured = models.BooleanField(default=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
time_stamp = models.DateTimeField(auto_now_add=True)
my product detail views.py is:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.all()
# context['reviews'] = Review.objects.filter(product=self.request.product)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
my product_detail.html is:
<!-- {% for review in reviews %}-->when i do this with my code it show me all the product
<!-- <h1>{{review.text}}{{review.rate}}</h1>-->
<!-- {% endfor %}-->
{% for review in product.review_set.all %}
{{ review.text }}
{% endfor %}
You do not need to make a query separately for your reviews. You can simply loop over them using your instance of Product in the template. Also for some reason you have set context_object_name = "object_list" try this:
{% for review in object.review_set.all %}
{{ review.text }}
{% endfor %}
Here review_set is simply the default related_name set by Django which is the related models name in lowercase with _set appended to it. You can chose to set the related name yourself like so if you want:
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE, null=True)
Anyway if you insist on modifying the view you can simply do this:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.filter(product=self.object)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
And then you can use this:
{% for review in reviews %}
{{ review.text }}
{% endfor %}

Django: ValidationError ['ManagementForm data is missing or has been tampered with']

Django: ValidationError ['ManagementForm data is missing or has been tampered with'] i have been getting this error when i use the forminline factory module, im sorry if my question isnt placed properly, this is my first time here.
my form template is this:
{% extends 'accounts/main-form.html'%}
{% load static %}
{% block title %}
<title>CRM | Form</title>
{% endblock %}
{% block link %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style1.css'%}">
{% endblock %}
{% block content %}
<div class="container">
<form action="" method="POST">
{{formset.management_form}}
{% for i in formset %}
{{i}}
{% endfor %}
<input type="submit" class="btn" value="submit">
</form>
</div>
{% endblock%}
this is the form code in views.py
def order_form(request, pk):
customers = Customer.objects.get(id=pk)
OrderFormSet = inlineformset_factory(Customer, Order, fields=('product', 'status',))
formset = OrderFormSet(request.POST)
if request.method == 'POST':
formset = OrderFormSet(request.POST, instance=customers)
if formset.is_valid():
formset.save()
return redirect('/')
context = {'formset': formset}
return render(request, 'accounts/order_form.html', context)
my models
from django.db import models
# Create your models here.
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Product(models.Model):
CATEGORY = (
('Indoor', 'Indoor'),
('OutDoor', 'Outdoor')
)
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
description = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True)
tag = models.ManyToManyField(Tag)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered')
)
customer = models.ForeignKey(Customer, null=True, on_delete= models.DO_NOTHING)
product = models.ForeignKey(Product, null=True, on_delete= models.DO_NOTHING)
date_created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def __str__(self):
return self.product.name
my form.py
from django.forms import ModelForm
from .models import Order
class Order_form(ModelForm):
class Meta:
model = Order
fields = ['product', 'status']

Django filter a queryset based on the template name

In my Django App, I have 2 models. One called Post and one called Categories. When a user clicks on a category, I want only the posts that are in that category to appear in the category detail view. For example if a user clicks on the medical category, I only want the posts in the medical category to appear.
Models:
class Category(models.Model):
title = models.CharField(max_length=200)
colorcode = models.CharField(max_length=20, blank=True, null=True)
description = models.TextField()
image = models.ImageField(blank=True, null=True)
slug = models.SlugField(unique=True)
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
sub_description = models.TextField(blank=True, null=True)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
image = models.ImageField(blank=True, null=True)
live = models.BooleanField(default=False)
slug = models.SlugField(unique=True)
Views:
class CategoryDetailView(DetailView):
model = Category
def get_context_data(self, **kwargs):
context = super(CategoryDetailView, self).get_context_data(**kwargs)
context['category_posts'] = Post.objects.filter(live=True)
return context
Template:
{% for post in category_posts %}
<div class="post">
<div class="post-title">
{{ post.title }}
</div>
<div class="post-author">
{{ post.author }}
</div>
</div>
{% endfor %}
In a DetailView, you have access to the actual object being rendered (in your case the Category instance) through self.object.
So in your get_context_data method you can do:
context['category_posts'] = Post.objects.filter(live=True, category=self.object)
Note that self.object might be None so you may want to deal with that case.

Finding the Cross-Section of two List views in one Django template

I have two models that feed one view.
models.py
class Item(models.Model):
item_name = models.CharField(max_length=100)
item_type = models.ForeignKey(Item_type, on_delete=models.SET_NULL, null=True)
owned_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)****
added_at = models.DateTimeField('date item added')
updated_at = models.DateTimeField('last update')
def __str__(self):
return self.item_name
class Item_status(models.Model):
item = models.ForeignKey(Item, on_delete=models.SET_NULL, null=True)
borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
loaned_at = models.DateTimeField(default=None, blank=True, null=True)
due_back = models.DateTimeField(default=None, blank=True, null=True)
def __time__(self):
return self.loaned_at
def itemname(self):
return (self.item.item_name)
I have the following view
views.py
class LoanedItemsByUserListView(LoginRequiredMixin,generic.ListView):
model = Item_status
template_name ='catalog/item_status_list_borrowed_user.html'
paginate_by = 10
def get_queryset(self):
return Item_status.objects.filter(borrower=self.request.user).order_by('due_back')
def get_context_data(self, **kwargs):
context = super(LoanedItemsByUserListView, self).get_context_data(**kwargs)
context['Owned_list'] = Item.objects.filter(owned_by=self.request.user, item_type = 1)
context['Loaned_list'] = Item_status.objects.exclude(borrower=self.request.user).exclude(borrower__isnull=True)
return context
I would like to find the cross section of the 'Owned_list' and the 'Loaned_list' in a single template
Something like
<h2>Loaned Books</h2>
{% if Owned_list %}
<ul>
{% for thing in Owned_list.item_name and in Loned_list.item.item_name %}
<li>
{{thing}}
</li>
{% endfor %}
</ul
{% else %}
<p>There are no books in the library.</p>
{% endif %}
I have take a look at the django documentation here https://docs.djangoproject.com/en/1.11/topics/class-based-views/generic-display/, and around SO but not found exactly what I am looking for.
Thanks!

Categories