1 from django.conf import settings
2 from django.db.models import signals, FieldDoesNotExist
3 from django.utils.text import get_text_list
4 from django.db import IntegrityError
5 from django.utils.translation import ugettext as _
7 # This little gem is borrowed from
8 # https://djangosnippets.org/snippets/1628/
10 def check_unique_together(sender, **kwargs):
12 Check models unique_together manually. Django enforced unique together only the database level, but
13 some databases (e.g. SQLite) doesn't support this.
16 from django.db.models import signals
17 signals.pre_save.connect(check_unique_together, sender=MyModelClass)
19 or use auto_add_check_unique_together(), see below
21 instance = kwargs["instance"]
22 for field_names in sender._meta.unique_together:
24 for field_name in field_names:
26 data = getattr(instance, field_name)
27 except FieldDoesNotExist:
28 # e.g.: a missing field, which is however necessary.
29 # The real exception on model creation should be raised.
31 model_kwargs[field_name] = data
33 query_set = sender.objects.filter(**model_kwargs)
34 if instance.pk != None:
35 # Exclude the instance if it was saved in the past
36 query_set = query_set.exclude(pk=instance.pk)
38 count = query_set.count()
40 field_names = get_text_list(field_names, _('and'))
41 msg = _(u"%(model_name)s with this %(field_names)s already exists.") % {
42 'model_name': unicode(instance.__class__.__name__),
43 'field_names': unicode(field_names)
45 raise IntegrityError(msg)
47 def auto_add_check_unique_together(model_class):
49 Add only the signal handler check_unique_together, if a database without UNIQUE support is used.
51 if 'sqlite' in settings.DATABASES['default']['ENGINE']:
52 signals.pre_save.connect(check_unique_together, sender=model_class)