You can also get the value as hex (if you want slightly shorter IDs, for use in URLs for example):

>>> Counter.next_hex('some-counter-that-is-quite-high')
40e

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

fromdjango.dbimportmodelsfromdjango.db.modelsimportFclassCounter(models.Model):"For generating unique IDs"key=models.CharField(max_length=50,primary_key=True)counter=models.IntegerField(default=0)@classmethoddefnext(cls,key='default'):"Increments and returns the next unused integer"try:cls.objects.filter(pk=key).update(counter=F('counter')+1)returncls.objects.get(pk=key).counterexceptcls.DoesNotExist:# This could raise an integrity error in a race condition :/returncls.objects.create(key=key,counter=0).counter@classmethoddefnext_hex(cls,key='default'):returnhex(cls.next(key)).replace('0x','').replace('L','')def__unicode__(self):returnu'%s = %s'%(self.pk,self.counter)