Reputation: 43
I'm on Django 1.9. I've a simple model with:
#Goods
class Goods(models.Model):
code = models.CharField(max_length=50)
decription = models.CharField(max_length=100)
...etc
#Vendors
class Vendors(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
...etc
And a class to define the multiple vendors to obtain a good.
#Purchase_options
class PurchaseOptions(models.Model):
preferred_vendor = models.BooleanField()
vendor = models.ForeignKey(Vendors)
good = models.ForeignKey(Goods)
Here's is the question: How can I make sure that only one vendor for a particular good can be set as preferred?.
Accepted values on table:
**Vendor | Product | Preferred**
V_01 | Good_01 | True
V_02 | Good_01 | False
V_03 | Good_01 | False
V_02 | Good_02 | True
V_04 | Good_02 | False
Wrong values on table:
**Vendor | Product | Preferred**
V_01 | Good_01 | True
V_02 | Good_01 | **True** <-There's already a preferred vendor.
V_03 | Good_01 | False
V_02 | Good_02 | True
V_04 | Good_02 | False
I'm using Django's admin interface to fill-up the data on Puchase_Options. I tried this:
1) Define a validator that, given the Preferred value and the product id, checks if this combination exists in the table:
def validator(preferred, id):
if Purchase_Option.objects.filter(good.id=id,preferred_vendor=preferred).exists():
Raise ValidationError("There's already a preferred vendor defined for this product")
But it's telling me that object Purchase_Options doesn't exist. I believe I can't actually query the database or handle querysets within a validator function.
2) I tried using the meta property unique-together("preferred_vendor","good_id"). That would work except that I must allow multiple combinations of False + Good_Id (because I've many Non-Preferred vendors for a good)... but only just 1 combination of True+Good_id.
I don't really know what else to try and I'm really looking forward to hearing your ideas. You saved me in multiple occasions before :D
Upvotes: 4
Views: 912
Reputation: 6331
You could use NullBooleanField
for preferred_vendor
, and unique_together
for preferred_vendor
and good
. Use True
for the one preferred vendor and NULL
instead of False
for all others.
This will allow you to have multiple pair of (good
, NULL
) and only one pair with (good
,True
). The drawback is you will be able to also have only one pair (good
,False
), but this shouldn't be a problem.
E.g.:
class PurchaseOptions(models.Model):
preferred_vendor = models.NullBooleanField()
vendor = models.ForeignKey(Vendors)
good = models.ForeignKey(Goods)
class Meta:
unique_together = ("preferred_vendor", "good")
then:
Vendor | Product | Preferred
V_01 | Good_01 | True
V_02 | Good_01 | NULL
V_03 | Good_01 | NULL
V_02 | Good_02 | True
V_04 | Good_02 | NULL
Upvotes: 4