billyJoe
billyJoe

Reputation: 2064

Resave a models into a try catch

this is a design question.

Suppose an Organisation with a name and a code

class Organisation(models.Model):
    """
    Class to manage Organisations.
    """
    name = models.CharField(_('Name'), max_length=50)
    code = models.CharField(_('Code'),
            max_length=8,
            editable=False,
            unique=True)

To avoid code problems, i use this save method:

def save(self, *args, **kwargs):
    """ override save method to add specific values """
    if self.pk is None:
        self.code = strftime('%y%m')+str(uuid4())[:4]
    try:
        super(Organisation, self).save(*args, **kwargs)
    except IntegrityError:
        self.code = strftime('%y%m')+str(uuid4())[:4]
        super(Organisation, self).save(*args, **kwargs)

As you can imagine, this code doesn't works, it's a bad code but i don't know how to do :'( EDIT: code format is a constraint, i cannot change it

Upvotes: 0

Views: 53

Answers (2)

Bernhard Vallant
Bernhard Vallant

Reputation: 50796

As I undestand it you are getting an IntegrityError because your code has to be unique. You could filter in the save method if an instance with the same code already exists:

def _generate_code(self):
    # have the whole code generation in one place
    return strftime('%y%m')+str(uuid4())[:4]

def save(self, *args, **kwargs):
    if self.pk is None:
        self.code = self._generate_code()
        while Organisation.objects.filter(code=self.code).exists():
            self.code = self._generate_code()
    super(Organisation, self).save(*args, **kwargs)

Maybe there are better ways to generate your code but don't know why it must be a piece of a uuid4. You could also try a random string with the character set you need.

Upvotes: 1

arocks
arocks

Reputation: 2882

If you want to create a unique suffix then you can check if it exists and keep trying till you generate a non-existent code.

def save(self, *args, **kwargs):
    """ override save method to add specific values """
    if self.pk is None:
        for i in range(100):    # Try 100 times to avoid infinite loops 
            code = strftime('%y%m')+str(uuid4())[:4]
            if not Organisation.objects.filter(code=code):
                 break
        self.code = code
    super(Organisation, self).save(*args, **kwargs)

Upvotes: 0

Related Questions