Suppose I'm Santa Claus and I'm making a site to keep track of kids' Christmas lists. I might have something like this:
class Kid(models.Model):
name = models.CharField()
class Gift(models.Model):
name = models.CharField()
class WishList(models.Model):
date_received = models.DateTimeField()
kid = models.ForeignKey(Kid, on_delete=CASCADE)
I have implemented the WishList model, instead of just linking Gifts to Kids with ForeignKeys directly, because I would like to keep track of individual Christmas wish lists discretely. I want to archive all the old Christmas lists as I received them. The most obvious way to implement this would be to add something like current = models.BooleanField()
to the WishList class, and then filter for wishlist.current=true
when I want to get the current wishlist for a given kid. However, there are two problems with this: 1. I don't know how the database query algorithm works behind the scenes, and I don't want to make the computer look through every list to find the current one, when 99% of the time that's the only one I'll be looking at, and 2. this doesn't prevent me from having two current wish lists, and I don't want to have to write special validator code to ensure that.
The second option I thought of would be to simply display the most recently received WishList. However, this doesn't satisfy all of my usage needs--I might have a kid write me saying, "wait, actually, disregard the list I sent in October, and use the one I sent in August instead." I could, of course, make a copy of the August list marked with today's date, but that feels both unnecessary and confusing.
The third option I thought of was that I could get rid of the ForeignKey field in WishList, and instead put the links in the Kid model:
class Kid(models.Model):
name = models.CharField()
current_wishlist = models.OneToOneField(WishList)
archived_wishlists = models.ManyToManyField(WishList)
This last one seems the most promising, but I am unfamiliar with OneToOneFields and ManyToManyFields, and am unsure if it is best practice. It also feels bad to have two separate fields for one type of model relation. Can anyone give me some guidance on what the best way to accomplish this would be?
CodePudding user response:
I'm no sure on what would be the best way, but you could also do something like:
class Kid(models.Model):
name = models.CharField()
current_wishlist = models.ManyToManyField(Gift)
archived_wishlists = models.ManyToManyField(Gift)
and when archiving a gift just do
kidObj.current_wishlist.remove(giftObj)
kidObj.archived_wishlist.add(giftObj)
and viewing them
listofgifts = kidObj.current_wishlist.all()
powerrangergifts = kidObj.current_wishlist.filter(name__icontains='Power Ranger')
CodePudding user response:
archived_wishlists = models.ManyToManyField(WishList)
it works but you now could add one whishlist to multiple kids kid - whishlist is a one-many relation therefor you have to put the foreign key into the "many model"
- I don't know how the database query algorithm works behind the scenes, and I don't want to make the computer look through every list to find the current one, when 99% of the time that's the only one I'll be looking at
well you dont have to know
- this doesn't prevent me from having two current wish lists, and I don't want to have to write special validator code to ensure that.
then go for the OnetoOne but you have to ensure the kid matches the one referenced in the whishlist