Home > Mobile >  Django CharField with dynamic default value
Django CharField with dynamic default value

Time:10-19

I want to add a new field to a PostgreSQL database.

It's a not null and unique CharField, like

dyn = models.CharField(max_length=31, null=False, unique=True)

The database already has relevant records, so it's not an option to

  • delete the database
  • reset the migrations
  • wipe the data
  • set a default static value.

How to proceed?


Edit

Tried to add a default=uuid.uuid4

dyn = models.CharField(max_length=31, null=False, unique=True, default=uuid.uuid4)

but then I get

Ensure this value has at most 31 characters (it has 36).


Edit 2

If I create a function with .hex (as found here)

def hex_uuid():
    """
    The UUID as a 32-character lowercase hexadecimal string
    """
    return uuid.uuid4().hex

and use it in the default

dyn = models.CharField(max_length=31, null=False, unique=True, default=hex_uuid)

I'll get

Ensure this value has at most 31 characters (it has 32).

Note: I don't want to simply get a substring of the result, like adjusting the hex_uuid() to have return str(uuid.uuid4())[:30], since that'll increase the collision chances.

CodePudding user response:

I ended up using one of the methods shown by Oleg

def dynamic_default_value():
    """
    This function will be called when a default value is needed.
    It'll return a 31 length string with a-z, 0-9.
    """
    alphabet = string.ascii_lowercase   string.digits
    return ''.join(random.choices(alphabet, k=31)) # 31 is the length of the string

with

dyn = models.CharField(max_length=31, null=False, unique=True, default=dynamic_default_value)

If the field was max_length of 32 characters then I'd have used the hex_uuid() present in the question.


If I wanted to make the dynamic field the same as the id of another existing unique field in the same model, then I'd go through the following steps.

CodePudding user response:

you can reset the migrations or edit it or create new one like:

python manage.py makemigrations name_you_want

after that:

python manage.py migrate same_name

edit: example for funcation:

def generate_default_data():
    return datetime.now()

class MyModel(models.Model):
     field = models.DateTimeField(default=generate_default_data)
  • Related