Django Unique Together (with foreign keys)
You can't.
The unique_together
clause is directly translated to the SQL
unique index. And you can only set those on columns of a single table, not a combination of several tables.
You can add validation for it yourself though, simply overwrite the validate_unique
method and add this validation to it.
Docs: http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.validate_unique
Django: Is there a way to add a foreign key field to unique_together?
you cannot. database constraints cannot contain those kind of data. you will have to check it programmatically before creating instances or write some validator
Unique together involving multiple foreign keys & a many to many field
Since only few d
entities had to have a corresponding price (rest will continue to have a generic common price), I ended up with the following structure.
class PricingTable(models.Model):
a = models.ForeignKey(A, on_delete=models.CASCADE)
price = MoneyField()
b = ArrayField(models.CharField(choices=CHOICES))
c = models.ForeignKey(C, on_delete=models.CASCADE)
d = models.ForeignKey("x.D", on_delete=models.CASCADE, blank=True, null=True)
class Meta:
ordering = ("a",)
unique_together = ("a", "b", "c", "d")
def validate_b(self):
# b can't be empty
if not len(self.b) >= 1:
raise ValueError
# each element in b needs to be unique
if not len(self.b) == len(set(self.b)):
raise ValueError
# each element in b needs to be unique together with a, c & d
query = PricingTable.objects.filter(
a=self.a, c=self.c, d=self.d, b__overlap=self.b
).exclude(pk=self.pk)
if query.count() > 0:
raise ValueError
def save(self, *args, **kwargs):
self.validate_b()
return super().save(*args, **kwargs)
class DBasedPricing(models.Model):
"""
Lookup table that tells (row exists) if we have D based pricing coupled with param A
If we do, query PricingTable.d=d, else PricingTable.d=None for correct pricing
"""
d = models.ForeignKey("x.D", on_delete=models.CASCADE)
a = models.ForeignKey(A, on_delete=models.CASCADE)
class Meta:
unique_together = ("d", "a")
This forces me to first do a lookup based on d
parameter, to check if pricing would be D
based or notd_id = None
if DBasedPricing.objects.filter(d_id=input_param.d, a_id=a.id).exists():
d_id = input_param.d
Which then adds another parameter to my usual queriesprice_obj = PricingTable.objects.filter(...usual query..., d_id=d_id)
Overall, at the cost of a single simple indexed lookup, I save on rows & of course complex DB structuring. Also, I ended up not having to re-enter all the existing pricing! Django unique combination of foreign keys
You have to set in the Meta class in the KeyList:
class KeyList(models.Model):
key_one = models.ForeignKey(KeyOne)
key_two = models.ForeignKey(KeyTwo)
key_three = models.ForeignKey(KeyThree)
list = models.CharField()
class Meta:
unique_together = (("key_one", "key_two", "key_three"),)
unique constraint on the basis of foreign model field value django
You can not put unique constraints across the relations. You can only put columns belonging to the current Model only in unique constraints or unique_together. However, you can try the following approach
class C(models.Model):
field1 = models.ForeignKey(A, ..)
field2 = models.ForeginKey(B, ..)
def validate_unique(self, exclude=None):
qs = C.objects.filter(field1=self.field1)
if qs.filter(B__field2=self.field2).exists():
raise ValidationError('Fields must be unique')
models.Model.validate_unique(self, exclude=exclude)
Also, note that this function will not be called automatically while saving the objects of model C, so you will have to call it explicitly. How to make two foreign keys to same model unique together?
I suggest you to use model.clean method:
class Friendship(models.Model):
person1 = models.ForeignKey(Person, related_name='person1')
person2 = models.ForeignKey(Person, related_name='person2')
def clean(self):
direct = FriendShip.objects.filter(person1 = self.person1, person2 = self.person2)
reverse = FriendShip.objects.filter(person1 = self.person2, person2 = self.person1)
if direct.exists() or reverse.exists():
raise ValidationError({'key':'Message')})
Related Topics
Memoization Library for Python 2.7
Writing List of Strings to Excel CSV File in Python
Possible Values from Sys.Platform
Does 'Anaconda' Create a Separate Pythonpath Variable for Each New Environment
Filename and Line Number of Python Script
Setting Up S3 for Logs in Airflow
Does Python Do Slice-By-Reference on Strings
Counting Cars Opencv + Python Issue
Is There a Function to Determine Which Quarter of the Year a Date Is In
Pandas Dataframe Column to List
Determine Prefix from a Set of (Similar) Strings
When Should an Attribute Be Private and Made a Read-Only Property
How to Check Task Status in Celery
Pairwise Crossproduct in Python
How to Build a Systemtray App for Windows