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
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.