Login

True Unique Boolean Model Decorator

Author:
kunitoki
Posted:
May 15, 2012
Language:
Python
Version:
1.4
Score:
1 (after 1 ratings)

This class decorator will help you when you want to keep a unique boolean (think a 'default' field which should only be only one set to true in a group).

The interesting thing with this, is that it's possible to assign a subset of fields to be used, so that the uniqueness of the field will be guaranteed among only the subset (look at the Example section in the code to understand this behaviour).

This is a better and improved way of doing http://djangosnippets.org/snippets/2676/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from functools import wraps


def unique_boolean(field, subset=[]):
    """
    Allows to specify a unique boolean for a model.
    """
    def cls_factory(cls):
        def factory(func):
            @wraps(func)
            def decorator(self):
                kwargs = { field: True }
                for arg in subset:
                    if getattr(self, arg):
                        kwargs[arg] = getattr(self, arg)
                if getattr(self, field):
                    try:
                        tmp = self.__class__.objects.get(**kwargs)
                        if self != tmp:
                            setattr(tmp, field, False)
                            tmp.save()
                    except self.__class__.DoesNotExist:
                        if getattr(self, field) != True:
                            setattr(self, field, True)
                else:
                    if self.__class__.objects.filter(**kwargs).count() == 0:
                        setattr(self, field, True)
                return func(self)
            return decorator
        if hasattr(cls, 'save'):
            cls.save = factory(cls.save)
        return cls
    return cls_factory


# Example: keep the 'main' field unique for the phones of each user
@unique_boolean('main', subset=['user'])
class Phone(models.Model):
    user = models.ForeignKey(User)
    main = models.BooleanField()

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

Please login first before commenting.