92๐
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
18๐
My 2 cents, complementing the accepted response from @Wolph
You can add validation for it yourself though, simply overwrite the validate_unique method and add this validation to it.
This is a working example code someone could find usefull.
from django.core.exceptions import ValidationError
class MyModel(models.Model):
fk = models.ForeignKey(AnotherModel, on_delete=models.CASCADE)
my_field = models.CharField(...) # whatever
def validate_unique(self, *args, **kwargs):
super().validate_unique(*args, **kwargs)
if self.__class__.objects.\
filter(fk=self.fk, my_field=self.my_field).\
exists():
raise ValidationError(
message='MyModel with this (fk, my_field) already exists.',
code='unique_together',
)
- [Django]-How do I package a python application to make it pip-installable?
- [Django]-Django CMS fails to synch db or migrate
- [Django]-Django: guidelines for speeding up template rendering performance
12๐
My solution was to use Djangoโs get_or_create. By using get_or_create, a useless get will occur if the row already exists in the database, and the row will be created if it does not exist.
Example:
extension = Extension.objects.get(pk=someExtensionPK)
userProfile = UserProfile.objects.get(pk=someUserProfilePK)
UserProfileExtension.objects.get_or_create(extension=extension, userprofile=userProfile)
- [Django]-How to move a model between two Django apps (Django 1.7)
- [Django]-How to override css in Django Admin?
- [Django]-Using Python's os.path, how do I go up one directory?
5๐
From django 2.2+ versions, it is suggested to use constraint & Index as model class meta option:
https://docs.djangoproject.com/en/3.2/ref/models/options/#django.db.models.Options.unique_together
https://docs.djangoproject.com/en/3.2/ref/models/options/#django.db.models.Options.constraints
class UniqueConstraintModel(models.Model):
race_name = models.CharField(max_length=100)
position = models.IntegerField()
global_id = models.IntegerField()
fancy_conditions = models.IntegerField(null=True)
class Meta:
constraints = [
models.UniqueConstraint(
name="unique_constraint_model_global_id_uniq",
fields=('global_id',),
),
models.UniqueConstraint(
name="unique_constraint_model_fancy_1_uniq",
fields=('fancy_conditions',),
condition=models.Q(global_id__lte=1)
),
models.UniqueConstraint(
name="unique_constraint_model_fancy_3_uniq",
fields=('fancy_conditions',),
condition=models.Q(global_id__gte=3)
),
models.UniqueConstraint(
name="unique_constraint_model_together_uniq",
fields=('race_name', 'position'),
condition=models.Q(race_name='example'),
)
]
- [Django]-Inject errors into already validated form?
- [Django]-How to force a user logout in Django?
- [Django]-Are Django SECRET_KEY's per instance or per app?
3๐
You need to call Models.full_clean() method to call validate_unique for foreignKey. You can override save() to call this
class UserProfileExtension(models.Model):
extension = models.ForeignKey(Extension, unique=False)
userprofile = models.ForeignKey(UserProfile, unique=False)
user = models.ForeignKey(User, unique=False)
def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)
class Meta:
unique_together = (("userprofile", "extension"),
("user", "extension"),
# How can I enforce UserProfile's Client
# and Extension to be unique? This obviously
# doesn't work, but is this idea possible without
# creating another FK in my intermediary model
("userprofile__client", "extension"))
- [Django]-Adding to the "constructor" of a django model
- [Django]-Can't install via pip because of egg_info error
- [Django]-What is the difference between {% load staticfiles %} and {% load static %}
2๐
from django.core.exceptions import ValidationError
.....
class UserProfileExtension(models.Model):
extension = models.ForeignKey(Extension, unique=False)
userprofile = models.ForeignKey(UserProfile, unique=False)
user = models.ForeignKey(User, unique=False)
def validate_unique(self, *args, **kwargs):
super(UserProfileExtension, self).validate_unique(*args, **kwargs)
query = UserProfileExtension.objects.filter(extension=self.extension)
if query.filter(userprofile__client=self.userprofile.client).exists():
raise ValidationError({'extension':['Extension already exits for userprofile__client',]})
The first query is to filter all records in UserProfileExtension model which has the same extension we are putting in the current record.
Then we filter the query returned to find if it already contains userprofile__client which we are passing in the current record.
- [Django]-How to get the ID of a just created record in Django?
- [Django]-What is pip install -q -e . for in this Travis-CI build tutorial?
- [Django]-Django change default runserver port
1๐
Another possible solution is to add this on your save method from your Model:
def save(self, *args, **kwargs):
unique = self.__class__.objects.filter( extension =self.extension, userprofile=self.userprofile )
if unique.exists():
self.id = unique[0].id
super(self.__class__, self).save(*args, **kwargs)
- [Django]-How to use refresh token to obtain new access token on django-oauth-toolkit?
- [Django]-Add a custom button to a Django application's admin page
- [Django]-How to validate an Email address in Django?