Generate a random alphanumeric string as a primary key for a model

前端 未结 3 1940
Happy的楠姐
Happy的楠姐 2021-02-03 12:28

I would like a model to generate automatically a random alphanumeric string as its primary key when I create a new instance of it.

example:

from django.d         


        
相关标签:
3条回答
  • 2021-02-03 12:43

    Here's how I would do it without making the field a primary key:

    from django.db import IntegrityError
    
    class MyTemporaryObject(models.Model):
        auto_pseudoid = models.CharField(max_length=16, blank=True, editable=False, unique=True)
        # add index=True if you plan to look objects up by it
        # blank=True is so you can validate objects before saving - the save method will ensure that it gets a value
    
        # other fields as desired
    
        def save(self, *args, **kwargs):
            if not self.auto_pseudoid:
                self.auto_pseudoid = generate_random_alphanumeric(16)
                # using your function as above or anything else
            success = False
            failures = 0
            while not success:
                try:
                    super(MyTemporaryObject, self).save(*args, **kwargs)
                except IntegrityError:
                     failures += 1
                     if failures > 5: # or some other arbitrary cutoff point at which things are clearly wrong
                         raise
                     else:
                         # looks like a collision, try another random value
                         self.auto_pseudoid = generate_random_alphanumeric(16)
                else:
                     success = True
    

    Two problems that this avoids, compared to using the field as the primary key are that:

    1) Django's built in relationship fields require integer keys

    2) Django uses the presence of the primary key in the database as a sign that save should update an existing record rather than insert a new one. This means if you do get a collision in your primary key field, it'll silently overwrite whatever else used to be in the row.

    0 讨论(0)
  • 2021-02-03 12:52

    One of the simplest way to generate unique strings in python is to use uuid module. If you want to get alphanumeric output, you can simply use base64 encoding as well:

    import uuid
    import base64
    uuid = base64.b64encode(uuid.uuid4().bytes).replace('=', '')
    # sample value: 1Ctu77qhTaSSh5soJBJifg
    

    You can then put this code in the model's save method or define a custom model field using it.

    0 讨论(0)
  • 2021-02-03 13:01

    Try this:

    The if statement below is to make sure that the model is update able.

    Without the if statement you'll update the id field everytime you resave the model, hence creating a new model everytime

    from uuid import uuid4
    from django.db import IntegrityError
    
    class Book(models.Model):
        id = models.CharField(primary_key=True, max_length=32)
    
        def save(self, *args, **kwargs):
            if self.id:
                super(Book, self).save(*args, **kwargs)
                return
    
            unique = False
            while not unique:
                try:
                    self.id = uuid4().hex
                    super(Book, self).save(*args, **kwargs)
                except IntegrityError:
                    self.id = uuid4().hex
                else:
                    unique = True
    
    0 讨论(0)
提交回复
热议问题