Creating default id in Django from function string and prefix

What I need to do is run the function and add a prefix to the beginning of the results returned by that function. This needs to be done every time a new instance of my model is created.

What I have tried ....

The following will not work because you cannot add a line to the function and set the ID as s_<function name etc>

, not the results of the function.

APP_PREFIX = "_s"
id = models.CharField(primary_key=True, max_length=50, unique=True,
                      default="{}{}".format(APP_PREFIX, make_id))

      

And it won't pass the prefix to the function, because Django will generate the same key every time the function is called this way, dont know why tho:

id = models.CharField(primary_key=True, max_length=50, unique=True,
                      default=make_id(APP_PREFIX))

      

This won't work either:

id = models.CharField(primary_key=True, max_length=50, unique=True,
                      default=make_id + APP_PREFIX)

      

Or that:

id = models.CharField(primary_key=True, max_length=50, unique=True,
                      default=make_id() + APP_PREFIX)

      

How can this be achieved?

I could overwrite the method save()

and achieve this, but there must be a way to do it with a default parameter in the field!

+3


source to share


3 answers


I found a way to achieve this on my model:



PREFIX = settings.PREFIXES['THIS']
def get_id():
  return make_id(PREFIX)

    class MyModel(models.Model):
        id = models.CharField(primary_key=True,unique=True,
                                  default=get_id,)

      

+1


source


You can create your own manager for your model and override the method create()

. Then in the method, create()

you can generate the ID field by explicitly calling the function make_id

. The only thing is that you shouldn't set a default property for the id field.

So, the model will look something like this:

class MyModel(models.Model):
  id = models.CharField(primary_key=True, max_length=50, unique=True)
  objects = MyModelManager()

      

Then the implementation MyModelManager

should look something like this:

class MyModelManager(models.Manager):
  def create(self, **kwargs):
    kwargs['id'] = make_id()
    return super(MyModelManager, self).create(**kwargs)

      



Of course, you must add any other parameters to the create method as needed to instantiate your model.

Object instantiation is MyModel

done as follows:

my_model = MyModel.objects.create()

      

Alternatively, if you want to use the default property, the following should work for you:

class MyModel(models.Model):
  APP_PREFIX = "_s"
  id = models.CharField(primary_key=True, max_length=50, unique=True,
                        default=lambda: generate_id(MyModel.APP_PREFIX))

def generate_id(prefix):
  return make_id() + prefix

      

+1


source


Method rewriting save

should be easy to implement:

from django.db import models

class YourModel(models.Model):
    id = models.CharField(primary_key=True, max_length=50, unique=True)
    # other fields for YourModel

    def make_id():
        return base64.b64encode(uuid.uuid4().bytes).decode("utf-8")

    def save(self, *args, ***kwargs):
        if not self.id:
            self.id = self.make_id()
        super(YourModel, self).save(*args, **kwargs)

      

make_id

Not a method after all YourModel

, but it's just a small change in the code. In the method, save

you can combine "s_" or whatever you need. The ID is only generated if the record does not have an ID (which does not exist yet).

Using self.pk

might be an alternative (and possibly) better approach. You can omit explicit field creation id

.

+1


source