I Have a table Product and a table Variation, Variation has ManyToOne relation i.e. ForeignKey with the table.
I want only first object of Variation, so that I can render it fields, which I want.
The way I am currently implementing to call the first object in html page:
{{item.variation.price_set.first}}
Note: {{item}} is my product object or instance.
Html file:
<div class="carousel-inner">
{% for item in TopItems %}
{% if item.image %}
<div class="carousel-item active">
<img class="d-block img-fluid mx-auto m-auto" src="{{item.image.url}}" alt="{{item.name}}">
<p>{{item.name}}</p>
<p>{{item.variation.price_set.first}}</p>
<p>{{item.variation_set.first}}</p>
{% if item.variation.promotion_price_set.first%}
<h2 class="text-primary">
{{item.variation.promotion_price}}
</h2>
<h2 class="text-primary">
{{item.variation.price}}
</h2>
{% else %}
<h2 class="text-primary">
{{item.variation.price}}
</h2>
{% endif %}
</div>
{% endif %}
{% endfor%}
</div>
Models.py
class Product(models.Model):
name = models.CharField(max_length=255)
short_description = models.TextField(max_length=255)
long_description = models.TextField(max_length=255, blank=True)
image = ResizedImageField(
size=[550, 300], quality=70, upload_to='product_images/%Y/%m/%d')
#image = models.ImageField(upload_to='product_images/%Y/%m/%d')
slug = AutoSlugField(unique=True, always_update=False,
populate_from="name")
top_item = models.BooleanField(default=False)
is_available = models.BooleanField(default=True)
category = models.ForeignKey(
Category, related_name="product", on_delete=models.CASCADE)
subcategory = models.ForeignKey(
SubCategory, related_name="sub", on_delete=models.CASCADE, null=True, blank=True)
objects = models.Manager()
available = AvailableManager()
class Meta:
ordering = ("name",) # vai ser ordenado pelo nome não o ID
def get_absolute_url(self):
return reverse("product:detail", kwargs={"slug": self.slug})
class Variation(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
name = models.CharField(
max_length=80, blank=True, null=True)
price = models.FloatField()
promotion_price = models.FloatField(blank=True, null=True)
stock = models.PositiveIntegerField(default=1)
is_available = models.BooleanField(default=True)
availableVariation = AvailableManagerVariation()
objects = models.Manager()
def __str__(self):
return self.name or self.product.name
Views.py, the below method is passing all records to the template.
def get_context_data(self, **kwargs):
context["TopItems"]= Product.objects.filter(top_item=True)
So, How can I get only first record of variaton, so that I can show respective prices?
You can use nested loops, for accessing only first promotion price as well as price in the following way:
This is a minimal reproducible example, as not able to understand your design.
{% for item in TopItems %}
<div>
<p> {{item.name}} </p>
<p>{{forloop.counter}}st variation</p>
{% for variation in item.variation_set.all %}
{% if forloop.counter0 < 1 %}
<p>First variation price of - {{variation.price}}</p>
{% comment %}It will give only first price {% endcomment %}
<p>First variation promotion price - {{variation.promotion_price}}</p>
{% comment %}It will give only first promotion price{% endcomment %}
{% endif %}
{% endfor %}
</div>
<br>
{%endfor%}
Note: There must be a space between template tags, as so write it as {% endif %} not {%endif%}, similarly for {% endfor %} not {%endfor%}.
Note: It will be better, if you pass your context keys in snake_case rather than PascalCase, so it can be passed as top_items rather than TopItems.
Related
TypeError at /vegetables/
get_object_or_404() got an unexpected keyword argument 'slug'
views.py
from django.shortcuts import render, get_object_or_404
from .models import Category
from .models import Product
def allProductCategory(request,c_slug=None):
c_page=None
products=None
if c_slug!=None:
c_page=get_object_or_404(Category,slug=c_slug)
products=Product.objects.all().filter(category=c_page,available=True)
else:
products=Product.objects.all().filter(available=True)
return render(request, 'category.html',{'category':c_page,'products':products})
urls.py
app_name='ecommerceapp'
urlpatterns = [
path('',views.allProductCategory,name='allProductCategory'),
path('<slug:c_slug>/',views.allProductCategory,name='products_by_category'),
]
Includes 2 tables-Category, Product
models.py
class Category(models.Model):
name = models.CharField(max_length=250,unique=True)
slug = models.SlugField(max_length=250,unique=True)
desc = models.TextField(blank=True)
image = models.ImageField(upload_to='category',blank=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return '{}'.format(self.name)
def get_url(self):
return reverse('ecommerceapp:products_by_category',args=[self.slug,])
class Product(models.Model):
name = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=250, unique=True)
desc = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
image = models.ImageField(upload_to='product', blank=True)
stock = models.IntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('name',)
verbose_name = 'product'
verbose_name_plural = 'products'
def __str__(self):
return '{}'.format(self.name)
Base.html is created. header.html, navbar.html, footer.html are included in base.html. Other than these three a block content and endblock is created in base.html.
category.html
{% extends 'base.html' %}
{% load static %}
{% block metadescription %}
{% if category %}
{{ category.description|truncatewords:155 }}
{% else %}
Welcome to ZUPER Store where you can get everything.
{% endif %}
{% endblock %}
{% block title %}
{% if category %}
{{ category.name }} - ZUPER store
{% else %}
All that you need - ZUPER store
{% endif %}
{% endblock %}
{% block content %}
{% if category %}
<div>
<div>
<p>Our products</p>
</div>
</div>
{% endif %}
<div>
{% if category %}
<img src="{{category.image.url}}" alt="{{category.name}}">
</div>
<br>
<div>
<h1>{{category.name}}</h1>
<p>{{category.description}}</p>
</div>
{% else %}
<div>
<img src="{% static 'images/Banner.png' %}" alt="Our products" width="500px;" height="100px;">
</div>
<br>
<div>
<h1>Our product collections</h1>
<p>Dummy content</p>
</div>
{% endif %}
<div>
<div>
{% for product in products %}
<div>
<div>
<img src="{{product.image.url}}" alt="{{product.name}}">
<div>
<h4>{{product.name}}</h4>
<p>{{product.price}}</p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
I'am getting this error when I click on the hyperlink vegetables and cotton dress.
Code below checks whether a user added a product in cart or not. If it is added to cart by this current user it should show remove from cart button else it should show a simple form to add product in cart.
{% for ordereditem in item.ordereditems_set.all %}
{% if ordereditem.quantity > 0 and ordereditem.user.username == user.username %}
Remove from cart
{% elif not ordereditem %} # here!
<!-- else if there is no record of 'ordereditem' from current user show this form to add it to cart-->
<form class="d-flex justify-content-left" method="POST" action="{{ item.get_add_to_cart_url }}">
{% csrf_token %}
<input type="number" name="number" value="1">
<input type="submit" value="Add to cart">
</form>
{% endif %}
{% endfor %}
the problem lies here {% elif not ordereditem %} it seems like my current if statement doesn't meet the condition I expect. I tried using {% else %} but it still shows the form even after adding product to cart.
This is how models look like:
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
discount_price = models.DecimalField(max_digits=5,
decimal_places=2, verbose_name='Discount', null=True, blank=True)
image = models.ImageField(upload_to='products/%Y/%m/%d/')
image_cover = models.ImageField(upload_to='products/%Y/%m/%d/')
description = models.TextField()
slug = models.SlugField(max_length=150, blank=True, null=True)
category = models.CharField(max_length=15, choices=CATEGORY_CHOICE)
label = models.CharField(max_length=10, choices=LABEL_CHOICE)
associated_items = models.ManyToManyField("self", blank=True, null=True)
class OrderedItems(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
items = models.ManyToManyField(OrderedItems)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
Here is the github link. Thank You
You need {% empty %} here:
{% for ordereditem in item.ordereditems_set.all %}
...
{% empty %}
No items
{% endfor %}
I have a list that is generated by a method on one of my models. On the home page it works wonderfully, however when I go to a detail view of one project I can access all the parts of that project as they are direct fields of the Model, but I can't access the items in the list.
Model:
class Project(models.Model):
date_published = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
area = models.ForeignKey(Area, on_delete=models.PROTECT)
title = models.CharField(max_length=128, unique=True)
slug = models.SlugField(max_length=64)
summary = models.CharField(max_length=256)
others = models.CharField(max_length=128, blank=True)
deadline = models.DateField(null=True, blank=True)
priority = models.ForeignKey(Priority, on_delete=models.PROTECT)
closed = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.title)
super(Project, self).save(*args, **kwargs)
#property
def updates(self):
updates = []
sequence_id = 1
categories = set(self.update_set.all().values_list(
'category__id', flat=True))
for cat_id in categories:
a = Update.objects.filter(
project=self, category__id=cat_id).order_by('added').last()
if cat_id == sequence_id:
updates.append(a)
else:
for i in range(cat_id - sequence_id):
updates.append('null')
updates.append(a)
sequence_id = cat_id
sequence_id += 1
return updates
class Update(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
category = models.ForeignKey(UpdateCategory, on_delete=models.PROTECT)
update = models.TextField(max_length=240, blank=True)
added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.update
The view is simple:
class ProjectDetailView(DetailView):
template_name = 'project_portal/project_detail.html'
queryset = Project.objects.all()
and here is the dynamic url that I am using:
path('project/<int:pk>/',
ProjectDetailView.as_view(), name='project_detail'),
As for the template, I'm lost, here is one of the things I have tried:
<!DOCTYPE html>
{% extends "project_portal/base.html" %}
{% block home %}
<div id="main">
<div id="content">
<div>
<h1>{{ object.title }}</h1>
<h1>hello</h1>
{% if object_list %}
{% for item in updates %}
<p>{{ item }}</p>
{% endfor %}
{% else %}
<h2>No records found for this project</h2>
{% endif %}
</div>
</div>
</div>
{% endblock %}
What do I need to do to access the "updates" list that gets generated?
update is a property of the model instance, you need to access it from there like any other attribute. Also note, there is no object_list in a detail view.
<div>
<h1>{{ object.title }}</h1>
<h1>hello</h1>
{% for item in object.updates %}
<p>{{ item }}</p>
{% endfor %}
</div>
I would like a list of Articles tagged associated with Stories to be rendered on rows exclusive to their Story. Currently the template returns only articles from the last Story on three separate rows. The code as written and understood is:
Many Articles can belong to a single Story.
/models.py
class Story(models.Model):
title = models.CharField(max_length=200, default= "")
description = models.TextField()
publication_date = models.DateTimeField()
class Article(models.Model):
feed = models.ForeignKey(Feed)
title = models.CharField(max_length=200)
url = models.URLField()
publication_date = models.DateTimeField()
story = models.ManyToManyField(Story, default=None, blank=True)
Using queries, get a list of all story_ids. If entry in story_id_lst is equal to story_id in articles then append that story to row list.
/views.py
def articles_list(request):
articles = Article.objects.all()
story_id_lst = articles.values_list('story').distinct()
for entry in story_id_lst:
rows = articles.filter(story=entry)
Running that code in the shell returns three list, one empty, one with all articles matched to story 1 and one with all articles matched to story 2. I believe the problem is somewhere in the following code.
/views.py
return render(request, 'news/articles_list.html', {'rows': rows})
/articles_list.html
<div class="container" style="background-color: #DCDCDC; border-radius: 25px;">
<div class="row">
{% for row in rows %}
<div class="col-md-12">
{% for entry in row %}
<div class="container-fuild">
<div class="col-md-4" >
<h2>{{entry.title}}</h2>
<div>
<p>View Details</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
I see you've made extensive changes to your question..
If an Article can belong to a single Story, then Article should have a foreign key to Story (not a many-to-many relation):
class Story(models.Model):
title = models.CharField(max_length=200, default= "")
class Article(models.Model):
story = models.ForeignKey(Story, default=None, blank=True)
title = models.CharField(max_length=200)
url = models.URLField()
then the view can be written as:
def articles_list(request):
articles = Article.objects.all()
return render(request, 'news/articles_list.html', {'articles': articles})
and the template:
{% regroup articles by story as story_list %}
<ul>
{% for story in story_list %}
<li>{{ story.grouper }}
<ul>
{% for article in story.list %}
<li>{{ article.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
I have a this models
class Project(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=200, null=True, blank=True)
creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)
group_owner = models.ForeignKey(User)
def __str__(self, y):
return smart_str(self.name)
class Note(models.Model):
title = models.CharField(max_length=50, null=True, blank=True)
content = models.CharField(max_length=1000)
creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_date = models.DateTimeField(auto_now_add=False, auto_now=True)
projectId = models.ForeignKey(Project, on_delete=models.CASCADE)
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return smart_str(self.title)
which i would like to join them in one view, which would be shown when someone enters to this url http://localhost.com:8000/project/ID.
obviously the ID will depend in Project.id and it will have to get all the Notes that are related to it.
Meanwhile my views.py looks like this
class ProjectDetail(generic.DetailView):
model = Project
template_name = 'scribere/project/detail.html'
def get_queryset(self):
return Project.objects.filter(group_owner__exact=self.request.user.id)
class ProjectNoteList(generic.ListView):
context_object_name = 'project_note_list'
template_name = 'scribere/note/index.html'
def get_queryset(self):
return Note.objects.filter(userid__exact=self.request.user.id, projectId__exact=self.kwargs['pk'])
and the template
{% extends "base/adminsNavBar.html" %}
{% load i18n %}
{% block head_title %}{% trans 'Projects Details' %}{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumb"><p>{% trans 'Project Details' %}</p></div>
{% endblock %}
{% block content %}
<div class='row'>
{% trans 'Back' %}
{% trans 'Notes' %}
</div>
<div>
{{project.name}}
</div>
<div class = "note-list">
<ul>
{% for note in project_note_list %}
<li>
{{note}}
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
which doesn't load any information about the note. What am i missing?
Unless you are populating project_note_list with some information, there will be nothing to iterate over.
By virtue of the ForeignKeys, and having a Many to one relation the project object will have a set of notes associated with it, without having to look them up.
You should be able to query them using project.note_set.all() or in your template by using:
{% for note in project.note_set %}