0

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.

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145

2 Answers2

1

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.

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
0

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)
Hashem
  • 595
  • 1
  • 3
  • 8
  • Thanks for trying to help Hashem but I don't want to reset the migrations or that kind of gymnastics (as I mentioned in the question). – Tiago Martins Peres Oct 18 '22 at 13:41
  • 1
    He wants to add value to that field which is unique and not null and not also default. Which is not achievable by only running migration or editing it – Hemal Patel Oct 18 '22 at 13:42
  • I got you, you can put default value as a function, in this function you can generate unique value for example with uuid4 – Hashem Oct 18 '22 at 13:54