- Author:
- kunitoki
- Posted:
- May 15, 2012
- Language:
- Python
- Version:
- 1.4
- Tags:
- model unique boolean
- 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
- "Magic Link" Management Command by webology 3 weeks ago
- Closest ORM models to a latitude/longitude point by simonw 3 weeks ago
- Log the time taken to execute each DB query by kennyx46 3 weeks, 1 day ago
- django database snippet by ItsRLuo 3 weeks, 6 days ago
- Serialize a model instance by chriswedgwood 1 month, 3 weeks ago
Comments
Please login first before commenting.