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. Browser-native date input field by kytta 1 month, 1 week ago
  2. Generate and render HTML Table by LLyaudet 1 month, 2 weeks ago
  3. My firs Snippets by GutemaG 1 month, 3 weeks ago
  4. FileField having auto upload_to path by junaidmgithub 3 months ago
  5. LazyPrimaryKeyRelatedField by LLyaudet 3 months, 1 week ago

Comments

Please login first before commenting.