Model Relationship django - django

I'd appreciate your help. I have two models. In the Bids model you will find current_bid_cmp. I would like from the ListingAuctions model to be able to access the corresponding current_bid_cmp of the Bids model. I only have found information to do querys from the model which contains the foreingKey.
My view: I use get_context_data because I have been trying anothers querys. perhaps its not the more aproppiate
class index(ListView):
model = ListingAuctions
template_name = "auctions/index.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['object'] = ListingAuctions.objects.all()
return context
My Models:
class ListingAuctions(BaseModel):
title_auction = models.CharField('Title of the auction',max_length = 150, unique = True)
description = models.TextField('Description')
user = models.ForeignKey(User, on_delete = models.CASCADE)
category = models.ForeignKey(Category, on_delete = models.CASCADE)
initial_bid = models.FloatField(default=False)
content = models.TextField('Content of auction')
image = models.ImageField('Referential Image', null=True,
upload_to = 'images_auctions', max_length = 255, default= 'noimage.png')
class Bids(BaseModel):
user = models.ForeignKey(User, on_delete = models.CASCADE, related_name='offer_user')
listing_auctions = models.ForeignKey(ListingAuctions,null=True, on_delete= models.CASCADE, related_name='l_auctions')
initialized_bid = models.BooleanField(default=False)
current_bid_cmp = models.FloatField('Current Bid Cmp',blank=True, null=True )
offer = models.FloatField(default=0 ,null=True, blank=True)
My HTML Current bid: $ {{post.l_auctions.current_bid_cmp}} its my attemp l_auctions is the relate name from listing_auctions in Bids model. Post is a ListingAuction object:
{% for post in object_list %}
<div class=" col-md-4 mt-4 ">
<div class="card " style="width: 18rem;">
<a href="{% url 'auctions_detail' post.pk %}">
<img class="card-img-top img-fluid" src="{{ post.image.url }}" alt="Card image cap" >
</a>
<div class="card-body">
<a class="darklink" href="{% url 'auctions_detail' post.pk %}"> <h5 class="card-title">{{post.title_auction}}</h5></a>
<h5>Starting bid: $ {{post.initial_bid}}</h5>
<h5>Current bid: $ {{post.l_auctions.current_bid_cmp}}</h5>
<p class="card-text">{{post.content | truncatechars:700 }}</p>
Show Auction
</div>
</div>
</div>
{% endfor %}

Try this in your template:
{{ post.l_auctions.get.current_bid_cmp }}
Update
I modified your models a bit so they make more sense to me. You might need your BaseModel for a good reason so feel free to modify to your needs. I also changed some names. There's still things I see that don't make a lot of sense in them but I'll leave that to you.
models.py
from django.db import models
from django.conf import settings
class BaseModel(models.Model):
pass
class Category(models.Model):
name = models.CharField(max_length=20)
class Listing(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
title = models.CharField('Title of the auction', max_length=150, unique=True)
description = models.TextField('Description')
starting_bid = models.FloatField(default=False)
content = models.TextField('Content of auction')
image = models.ImageField('Referential Image', null=True,
upload_to='images_auctions', max_length=255, default='noimage.png')
def __str__(self):
return self.title
class Bid(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='offer_user')
listing = models.ForeignKey(Listing, null=True, on_delete=models.CASCADE, related_name='bids')
initialized_bid = models.BooleanField(default=False)
amount = models.FloatField('Current Bid', blank=True, null=True)
offer = models.FloatField(default=0, null=True, blank=True)
def __str__(self):
return str(self.amount)
class Meta:
get_latest_by = 'amount'
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for listing in object_list %}
<div class=" col-md-4 mt-4 ">
<div class="card " style="width: 18rem;">
<a href="#">
<img class="card-img-top img-fluid" src="{{ listing.image.url }}" alt="Card image cap">
</a>
<div class="card-body">
<a class="darklink" href="#">
<h5 class="card-title">{{ listing.title }}</h5></a>
<h5>Starting bid: $ {{ listing.starting_bid }}</h5>
<h5>Current bid: $ {{ listing.bids.latest }}</h5>
<p class="card-text">{{ listing.content | truncatechars:700 }}</p>
Show Auction
</div>
</div>
</div>
{% endfor %}
</body>
</html>
Here's an interactive session from a shell:
from django.contrib.auth import get_user_model
User = get_user_model()
admin = User.objects.get_or_create(username='admin')[0]
steve = User.objects.get_or_create(username='steve')[0]
jenny = User.objects.get_or_create(username='jenny')[0]
almond = User.objects.get_or_create(username='almond')[0]
from auctions.models import Category, Listing, Bid
c = Category.objects.get_or_create(name='General')[0]
l1 = Listing.objects.get_or_create(user=admin, category=c, title='Some title', description='description', starting_bid=1.00, content='content')[0]
b1 = Bid.objects.get_or_create(user=steve, listing=l1, amount=1.00)[0]
b2 = Bid.objects.get_or_create(user=jenny, listing=l1, amount=1.01)[0]
b3 = Bid.objects.get_or_create(user=almond, listing=l1, amount=1.02)[0]
>>> l1.bids.all()
<QuerySet [<Bid: 1.0>, <Bid: 1.01>, <Bid: 1.02>]>
You could get the max by:
Adding this to your class:
class Meta:
get_latest_by = 'amount'
and using listing.bids.latest()...
Or using aggregate:
from django.db.models import Max
>>> l1.bids.aggregate(max=Max('amount'))
{'max': 1.02}
The key thing to note is, listing.bids returns a "RelatedManager". This just means you can use familiar queryset methods like .all(), .get(), .filter(), .last(), .latest(), etc. Many more.
In your case, you should first review this article on how to get the max of a queryset. Then decide how you want to proceed. In the example above, I put a class Meta on the Bid model which lets you get the latest object back based on the amount. This assumes the latest amount is always the highest, which might not be true for your situation.
One other thing you could do is add a #property to your Listing model.
class Listing(models.Model):
...
#property
def max_bid(self):
from django.db.models import Max
max_bid = self.bids.aggregate(max=Max('amount'))
if max_bid.get('max'):
return max_bid['max']
return ""
Use in your template like this:
<h5>Current bid: $ {{ listing.max_bid }}</h5>

Use in your Jinja Template
{{object_list.0.l_auctions.current_bid_cmp}}

Related

How can show categories products in home page?

I want to show my all products row by row on the home page category-wise. Suppose, before starting a new row will have a heading(category name) and then will show all products according to the product category and then again will be starting a new row with a heading according to category. How can I do it? I applied the 3/4 methods but didn't work. Bellow, I've shown one of the methods. It doesn't work properly. Please help me.
views.py:
def home(request):
all_products = Products.objects.all()
context ={
"all_products":all_products,
}
return render(request,'home.html', context)
model.py:
class Category(models.Model):
title = models.CharField(blank=True, null=True, max_length = 100)
def __str__(self):
return str(self.title)
class Products(models.Model):
product_image = models.ImageField(blank=True, null=True, upload_to = "1_products_img")
product_title = models.CharField(blank=True, null=True, max_length = 250)
product_price = models.IntegerField(blank=True, null=True)
offer_price = models.IntegerField(blank=True, null=True)
created_date = models.DateTimeField(blank=True, null=True, auto_now=True)
product_category = models.ForeignKey(Category, related_name="categoty_related_name", on_delete=models.CASCADE, blank=True, null=True)
context_processors.py:
from .models import Category
def categories(request):
return {"categories":Category.objects.all()}
template:
{% for products in all_products %}
<h4 class="text-start montserrat_alternates_font ">{{products.product_category}}</h4>
<hr>
<!--- product card --->
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
{% if products.offer_price != None %}
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">
SALE
</div>
{% endif %}
<!-- Product image-->
<img class="card-img-top" style="height:150px;" src="{{products.product_image.url}}" alt="..." />
<!-- Product details-->
<div class="card-body ">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder product_title" style="">{{products.product_title}}</h5>
</div>
</div>
</div>
</div>
{% endfor %}
You have to change your thinking a bit :)
The easiest approach is to think from bigger "items" (like your Category) to smaller (Product).
Firstfully, use singular naming for models, like Product (without 's', just like you did with Category), because otherwise you will end up with confusing setting. Also, don't name fields with your model's name unless it's really necessary, product_category should be simply category and so on.
Secondly, open big for loop with Category that you pass as classic view's context:
def home(request):
categories = Category.objects.all()
context = {
"categories": categories,
}
return render(request,'home.html', context)
Then look at your ForeignKey field in Product:
class Products(models.Model):
...
category = models.ForeignKey(Category, related_name="products", ...)
The key is to use related name properly. In your template, try logic like this (using related_name smoothly in reversed relationship):
{% for category in categories %}
{{ category.title }}
{% for product in category.products.all %}
{{ product.title }} - {{ product.price }}
{% endfor %}
{% endfor %}
If you don't set related_name, then it would be accessible with <model_name>_set.all(), in this case product_set.all() (in templates without brackets, of course). Anyway, it will work like a charm :)

Django: How do I access a related object max value in html template

I am attempting to display a list of items for auction. For each item, I am wanting to also display the current bid price. The current bid price should be the max value or last added to the Bids class for each individual listing.
How do I render in my HTML the max Bid.bid_price for each item in my Listing.objects.all() collection?
Below are my models, views, and HTML.
Models:
class Listing(models.Model):
title = models.CharField(max_length=65, default="")
description = models.CharField(max_length=200, default="")
category = models.CharField(max_length=65, default="")
image = models.ImageField(blank=True, null=True, upload_to='images/')
listed_by = models.ForeignKey(User, on_delete=models.CASCADE, default="")
created_dt_tm = models.DateTimeField(auto_now_add=False, default=timezone.now())
class Bids(models.Model):
bidder = models.ForeignKey(User, on_delete=models.CASCADE, default="")
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, default="", related_name="bids")
bid_price = models.IntegerField(default=0)
created_dt_tm = models.DateTimeField(auto_now_add=False, default=timezone.now())
Views:
def index(request):
return render(request, "auctions/index.html", {
"listings": Listing.objects.all()
})
HTML:
{% for listing in listings %}
<div style=display:flex;margin:30px;border:lightseagreen;border-style:solid;height:150px;border-width:1px;width:40%>
<div style=width:25%;display:flex;>
{% if listing.image %}
<img src="{{listing.image.url}}" alt="Cannot display image" height="100px" style="margin-left:50px;">
{% endif %}
</div>
<div style=width:15%></div>
<div style=width:30%>
<div>{{listing.title}}</div>
<div style=font-size:10pt;>Description: {{listing.description}}</div>
<div style=font-size:10pt;>Category: {{listing.category}}</div>
<div style=font-size:10pt;>Current Price: ${{ listing.bids_object.bid_price }}</div>
<div style=font-size:10pt;>Created by:<br>{{listing.listed_by}}</div>
</div>
<div style=width:30%>
<div style=margin:10px;>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
what you need is django's annotate functionality to find the max of each Listing.
from django.db.models import Max
def index(request):
return render(request, "auctions/index.html", {
"listings": Listing.objects.all().values().annotate(
max_bid_amount = Max('bids__bid_price')
)
})
in your html you can then add following line for max_bid.
<div style=font-size:10pt;>Max Bid Amount:<br>{{listing.max_bid_amount}}</div>

How to query foreign key in Django with if conditions and do something if a condition is met

I'm working a website where I want to display product that are of two categories which are premium and free package and I want to filter all the premium package and label it with a star or a premium text to indicate it a premium package and for the free I'll do nothing. I don't know if I should user foreign key for this or tuple.
models.py:
STATUS_CHOICE = (
('draft', 'Draft'),
('in_review', 'In Review'),
('published', 'Published')
)
class Package_Category(models.Model):
title = models.CharField(max_length=10000, verbose_name="Title")
slug = models.SlugField(max_length=1000, unique=True)
def get_absolute_url(self):
return reverse("package-categories", args=[self.slug])
def __str__(self):
return self.title
class Meta:
verbose_name = "Package Category"
verbose_name_plural = "Package Categories"
class Vectors(models.Model):
title = models.CharField(max_length=10000, null=True, blank=True, verbose_name="Title")
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to="vectors-images/%Y/%m/%d/", default="default.jpg", verbose_name="Image Cover")
vec_file = models.FileField(upload_to='vector-uploads/%Y/%m/%d/', null=True, blank=True, verbose_name="Upload File")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="Category")
package_category = models.ForeignKey(Package_Category, on_delete=models.CASCADE, verbose_name="Package Category")
tags = models.ForeignKey(Tag, on_delete=models.CASCADE, verbose_name="Tag")
status = models.CharField(choices=STATUS_CHOICE, default="published", max_length=150, verbose_name='Status')
creator = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Creator")
creator_image = models.ImageField(upload_to="creators-images/%Y/%m/%d/", default="default.jpg", verbose_name="Creator Image")
created = models.DateTimeField(verbose_name="Created")
class Meta:
verbose_name = "Vector"
verbose_name_plural = "Vectors"
def get_absolute_url(self):
return reverse("vector-details", args=[self.slug])
def __str__(self):
return self.title
index.html:
{% for vector in vectors %}
<!-- Single Pricing Box -->
<div class="col-lg-4 col-md-6 col-sm-12">
<div class="_45lio">
<div class="_jk58o item_image_urip">
<img src="{{vector.image.url}}" class="img-fluid" alt="">
<i class="fa fa-download"></i>
<div class="image_urip_caption">
<div class="urip_caption_flex">
<div class="urip_author">
<div class="urip_avater">
<a href="author-detail.html.html" class="author-img">
<img src="assets/img/author.png" class="img-fluid" alt="" />
</a>
</div>
<div class="urip_avater_place">
<h3 class="urip_title">Adam vilson</h3>
<span>Liverpool, London</span>
</div>
</div>
</div>
<div class="urip_caption_last">
<div class="item_list_links">
<i class="fa fa-plus-circle"></i>
<i class="fa fa-heart"></i>
</div>
</div>
</div>
<div class="_io980 item_image_urip">
{% if package_category.premium %}
<h1>Premium Package</h1>
{% else %}
<h1>Free Package</h1>
{% endif %}
<h4 class="_95lp">{{vector.package_category}}</h4>
<span class="_ip76n">{{vector.category}}</span>
</div>
</div>
</div>
</div>
{% endfor %}
views.py:
from django.shortcuts import render
from . models import Vectors, Tag, Category, Package_Category
def index(request):
vectors = Vectors.objects.filter(status='published').order_by('-created')
context = {
'vectors': vectors,
}
return render(request, 'index.html', context)
you should do something like this if you are not using drf just by using the same model.
def index(request):
vectors = Vectors.objects.filter(status='published', package_category__title =="premimum").order_by('-created')
if vectors.exists():
// do something:
context = {
'vectors': vectors,
}
return render(request, 'index.html', context)
Although the best option would be to use serializers with drf

how to load same models section in two diffrent pages

i have a model name section connected with other model name subject with foreign key what i want to do is i want to load half of it content in other page and half of it content on other html
my models.py
class Section(models.Model):
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, related_name='section')
sub_section = models.CharField(max_length=500, blank=True)
title = models.CharField(max_length=5000, blank=False)
teacher = models.CharField(max_length=500, blank=False)
file = models.FileField(upload_to='section_vedios', blank=False)
about_section = models.TextField(blank=False, default=None)
price = models.FloatField(blank=False)
content_duration = models.DurationField(blank=False)
joined_date = models.DateTimeField(default=timezone.now,editable=False)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.subject.name
i mean i want to load {{section.title }} in one page and {{section.file }} on other when a person
click on the {{ section.title }}
here is my html
<ul>
{% for section in section_list %}
<div class="card">
<div class="card-header">
{{ subject.name}}
</div>
<div class="card-body">
<h5 class="card-title">{{ section.title }}</h5>
<p class="card-text"></p>
CLick Here
</div>
</div>
{% endfor %}
so when a person click on click here a another load up and in that i want to load another html and in that file load only related {{section.file.url}} will open up
if you want 2 pages, easy way is create generic view in views.py and write in class Section:
paginate_by = 2
this is complete tutorial:
https://docs.djangoproject.com/en/3.2/topics/pagination/#paginating-a-listview

Retrieve ImageField on Many-To-Many relationship

I have two apps related in a Many-To-Many relationship, Recipes and Tags, and I'm having trouble at retrieving a query of Tags having image != null and the Recipes that are currently PUBLISHED.
Recipe app: recipes/models.py
from django.db import models
from django.contrib.auth.models import User
from tags.models import Tag
DRAFT = 'D'
PUBLISHED = 'P'
RECIPE_STATES = (
(DRAFT, 'Draft'),
(PUBLISHED, 'Published')
)
class Recipe(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, unique=True)
date_created = models.DateField(auto_now_add=True)
date_modified = models.DateField(auto_now=True)
state = models.CharField(max_length=1, choices=RECIPE_STATES)
ingredients = models.TextField(blank=True)
introduction = models.TextField(blank=True)
preparation = models.TextField(blank=True)
tip = models.TextField(blank=True)
rating = models.IntegerField(blank=True)
diners = models.IntegerField(blank=True)
tags = models.ManyToManyField(Tag, blank=True)
def __str__(self):
return self.title
And the Tag app: tags/models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
image = models.ImageField(blank=True, null=True, upload_to='categories')
def __str__(self):
return self.name
recipes/views.py:
class HomeView(View):
def get(self, request):
queryset = Recipe.objects.filter(state=PUBLISHED)
last_recipes = queryset.order_by('-date_created')
top_recipes = queryset.order_by('-rating')
categories = Tag.objects.filter(image__isnull=False, recipe__state=PUBLISHED)
context = {
'last_recipes': last_recipes[:4],
'top_recipes': top_recipes[:4],
'categories': categories
}
return render(request, 'recipes/home.html', context)
When I try to retrieve that query from the views.py in home.html:
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
{% for category in categories %}
<a href="{% url 'category_recipes' category.name %}">
<div class="col-xs-6 col-sm-4 col-md-3 text-center">
<h3>{{ category.name }}</h3>
<img src="{{ category.image.url }}" alt="{{ category.name }}" height="100">
</div>
</a>
{% endfor %}
</div>
</div>
I'm getting this error:
ValueError at /
The 'image' attribute has no file associated with it.
I also have the tags populated with data:
Check, that Tag with id=20 not have '' (empty string) as value. You exclude only null values, but empty string is not checked.
I finally get it working using:
categories = Tag.objects.filter(image__isnull=False, recipe__state=PUBLISHED).distinct()
Now, categories in home.html is provided with data, and I'm not having trouble using category.image.url.