Reputation: 332
I want to have a Django CharField
in my models whose values will be generated as by concatenating fixed value and the value of an autogenerated value e.g value1: KAM001, Value2:KAM002 ...
Am stuck on how I can achieve that.
Upvotes: 4
Views: 2153
Reputation: 5048
There are many ways to answer to your question. It really depends on what the purpose of this field is and when do you want the code to be autogenerated (before or after the record is saved).
In the following code I'm defining a Charfield that stores codes with a fixed part ('KAM') and an incremental one ('001', '002', ...), none of these parts already defined elsewhere. When the object is saved, the field code, if empty, is populated incrementally.
class MyModel(models.Model):
code = models.CharField(blank=True, default='')
def save(self, force_insert=False, force_update=False):
if self.code == "":
existing_codes = MyModel.objects.all().order_by('-code')
if existing_codes.count() > 0:
new_code = int(existing_codes[0].code[1:]) + 1
else:
new_code = 0
self.code = 'KAM%03d' % new_code
super(MyModel, self).save(force_insert, force_update)
If you want to concatenate a string to an autoincrement field, the code is slightly less complex:
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
code = models.CharField(blank=True, default='')
def save(self, force_insert=False, force_update=False):
self.code = 'KAM%08d' % self.id
super(MyModel, self).save(force_insert, force_update)
If you want the code to be defined before saving the record you can use this approach:
class MyModel(models.Model):
code = models.CharField(blank=True, default=new_code)
@property
def new_code(self):
existing_codes = MyModel.objects.all().order_by('-code')
if existing_codes.count() > 0:
new_code = int(existing_codes[0].code[1:]) + 1
else:
new_code = 0
return 'KAM%03d' % new_code
but please note that this approach may generate duplicate values if two objects are instantiated before the first one is saved, so I discourage you to use this approach.
other approaches may use signals, triggers, etc. These are just some of many.
e.g., if you do not need to execute queries basing on the "Charfield field" I suggest you an alternative approach:
class MyModel(models.Model):
# ... your fields here
def my_code(self):
return 'KAM%08d'%self.pk # please note that I've added more padding zeroes
this can be called from your templates in this way:
{{obj.my_code}}
where obj is an instance of MyModel
if you need also to change the initial part for some records (the 'KAM' part) the "define on save" approach is the way to go.
Upvotes: 3