Search code examples
djangodjango-modelsmodel

How to override id field Django model


I'm looking for way to override id field mb with models.AutoField or something like that

But the main problem that i want to have specific id field

For example:

I want id field for user to start with number 0 and after that it might contains number or specific letters and this id will look like this : 0123456ABC and all of this should be unique

How can i do that? Should i override models.AutoField?

models.py

class User(models.Model):
   id = models.AutoFields()
user/0123456ABC

Solution

  • You need to try to save the new object with your chosen value for the unique field, and if that fails (with IntegrityError) modify the field until you do have a unique one.

    For example, if the canonical form is '0' + name, where name is something like 'John', you might use

    lname = name.strip().lower()
    for tries in range(8):
        mymodel.person_id = f'0{lname}'
        try:
            mymodel.save()
            break
        except Mymodel.IntegrityError:
            # confirm that the problem is lname already used
            if Mymodel.objects.filter( person_id = lname).exists():
                # do something to get or guess a unique lname
                continue # try save again, with modified lname
    
            else:
                raise  # some other database integrity issue so re-raise
    else:
        raise MyBadError( f"EEK! We tried {tries} times and failed!")
    

    As for what to do, that depends on what you are trying to accomplish. You might tell the user that his choice is already in use, try again. You might try again with a random 1-digit number appended, then a random 2-digit number, until success. Or other things.

    Note that its almost certainly best to try and catch the exception, because otherwise there is the unlikely possibility of a race (your confirmed unique person_id became non-unique before you saved it). Also (hopefully) > 90% chance that guessing and saving will succeed, so mostly only one DB operation not two.