0

I'm trying to create a random string into my DB for users. It's a part of passwordless login.

So I have a field that is supposed to generate a random string. But I just found out it does not. It acctually generates same string over and over. Maybe each 5-10 min it will generate a new string for several minutes.

My model looks like this.

class Random(models.Model):  
    user = models.OneToOneField('CustomUser', on_delete=models.CASCADE)
    random = models.CharField(max_length=25, default=uuid.uuid4().hex[:25].upper(), unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

Even though it's generating a 25 long string, it duplicates it over and over.

Since I have unique true, that results in next call for creating a string is not possible, since it's not unique.

How come it's creating unique each time?

sumpen
  • 503
  • 6
  • 19

2 Answers2

2

Your default value will be calculated before runtime, not during it. You'll need to define a callable object instead, which according to the Django documentation, will be called "every time a new object is created".

Example:

def calculate_random():
    return uuid.uuid4().hex[:25].upper()

class Random(models.Model):
    random = models.CharField(max_length=25, default=calculate_random, unique=True)
Rúben
  • 435
  • 2
  • 6
1

It's better to use UUIDField it is designed to store uuid and will be translated to corresponding DB type, uuid if database support it else CharField will be used as a fallback.

For example:

import uuid

class Random(models.Model):  
    random = models.UUIDField(default=uuid.uuid4, unique=True)

It's simple and straightforward.

funnydman
  • 9,083
  • 4
  • 40
  • 55
  • I don't understand why this is better than the other answer? Can I choose length of string with this solution also? – sumpen Jan 28 '20 at 12:20
  • 1
    @sumpen uuid4 format is strictly defined and has 36 characters, and can not has more or fewer, if this rule is broken (here much more of them) it is not `uuid` anymore. If you need *real* uniqueness don't truncate it. – funnydman Jan 28 '20 at 13:04
  • 1
    @sumpen this one is the _real_ correct answer, as it makes proper use of `uuid` - truncating the string representation of your uuid defeats the whole point of using uuids at all (and you'll have a hard time getting something better than a proper uuid if you want random unique identifiers). – bruno desthuilliers Jan 28 '20 at 13:18
  • @funnydman So this way, it will generate a new unique uuid with every new entry to the db? – sumpen Feb 05 '20 at 18:47
  • @sumpen yes, the unique UUID will be generated for every new record. – funnydman Feb 05 '20 at 19:24
  • @funnydman Damn. It worked on my dev setup but broke my production server :/ – sumpen Feb 05 '20 at 20:08
  • @funnydman fyi, it said that field random did not exist. I had to roll back. – sumpen Feb 05 '20 at 20:21