I'm doing one of the problems in the cs50 web course and I made a model for a listing on an auction site. For the sake of avoiding iterating through all bids on a listing, each listing has a Foreign Key called 'current_bid' that points to the latest bid. If the bid were to be deleted though, I want to be able to set the current bid to be the bid that came before it.
I've tried several approaches but the one that felt closest to working was making a function local to the model class that gets the lastest bid and tried to make it work by having on_delete call set(last_bid).
def last_bid(self):
bids = self.bids
last = None
for bid in bids:
if last is None:
last = bid
elif bid > last:
last = bid
return last
current_bid = models.ForeignKey('Bid', null=True, blank=True, on_delete=SET(last_bid),
related_name="running_bids")
It doesn't work because calling last_bid this way doesn't give it the needed 'self' parameter. Is there really no way for me to get a reference to the specific listing when the bid it's holding gets deleted?
CodePudding user response:
this is not an answer for your question, but it will solve your problem, because i believe you are looking in the wrong way
you have models, Listing and Bid
class Listing(models.Model):
title = models.CharField(max_length=20)
#... etc
class Bid(models.Model):
bid = models.IntegerField(default=0)
user = models.ForeignKey(User, on_delete=models.CASCADE)
listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
you don't need to asign current bid
as constant, current bid
is the biggest bid
that is asined to the listing
for example:
def my_listing_page(request):
listing_obj = Listing.objects.get(title = "my_listing")
biggest_bid = Bid.objects.filter(listing=listing_obj).order_by("bid").first()
in this scenario this function will always output biggest_bid
of this listing, and if it would be deleted someday, next one to it will become biggest or current
p.s i finished this course this is how i know your models
CodePudding user response:
Feels a little heavy for CS50. However, you can take the Django source code for one of the model deletion functions and re-purpose it for your needs, for example the models.CASCADE
code looks like this:
def CASCADE(collector, field, sub_objs, using):
collector.collect(
sub_objs,
source=field.remote_field.model,
source_attr=field.name,
nullable=field.null,
fail_on_restricted=False,
)
if field.null and not connections[using].features.can_defer_constraint_checks:
collector.add_field_update(field, None, sub_objs)
I believe the sub_objs
is specifically what you want to have access to so you can re-allocate them, you could do something like this:
def REALLOCATE_BID(collector, field, sub_objs, using):
bid = Bid.objects.get(... # get the bid somehow
sub_objs.update(current_bid=bid)