Home > other >  Is there a way to create an on_delete function that uses info from the specific model that holds a f
Is there a way to create an on_delete function that uses info from the specific model that holds a f

Time:07-22

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)
  • Related