Here are the models for reference:
class Listing(models.Model):
lister = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), related_name="listing")
title = models.CharField(max_length=80)
description = models.CharField(max_length=255)
image = models.ImageField(upload_to=user_directory_path, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
class Category(models.TextChoices):
ANTIQUE = "ANT", _("Antiques")
BOOK = "BOO", _("Books")
CLOTH = "CLO", _("Clothing, Shoes & Accessories")
COLLECT = "COL", _("Collectibles")
CRAFT = "CRA", _("Crafts")
ELECTRONIC = "ELE", _("Consumer Electronics")
INDUSTRIAL = "IND", _("Business & Industrial")
MOTOR = "MOT", _("Motors")
PET = "PET", _("Pet Supplies")
SPORT = "SPO", _("Sporting Goods")
TOY = "TOY", _("Toys & Hobbies")
category = models.CharField(max_length=3, choices=Category.choices)
active = models.BooleanField(default=True)
winner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), related_name="won",
null=True,
default=None)
def __str__(self):
return f"{self.id}:{self.title}"
class Bid(models.Model):
bidder = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), related_name="bid")
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bid")
bid_price = models.DecimalField(max_digits=11, decimal_places=2)
start_bid = models.BooleanField(default=False)
current_bid = models.BooleanField(default=True)
def __str__(self):
return f"{self.listing}: {self.bid_price}"
class Watchlist(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="watching")
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="watchers")
I managed to cobble together a solution using a loop in the view:
@login_required
def watchlist(request):
watch_list = Watchlist.objects.filter(user=request.user)
for i in watch_list:
i.current_price = Bid.objects.get(listing=i.listing, current_bid=True).bid_price
return render(request, "auctions/watchlist.html", {
"listings" : watch_list
})
How would i achieve the same output using only queries without iterating over the QuerySet ? I tried using annotate and prefetch_related but didn’t manage to find a solution.
Essentially i want to get all watchlist objects for the current user, then i want to get data from a model two relations away:
Watchlist > Listing (FK) > Bid (Reverse FK of Listing)
the query i ultimately want to add to each item in this queryset (Watchlist.objects.filter(user=request.user)) is for each listing get the bid_price WHERE current_bid=True
Thanks.