Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django 3 Dynamic Default Value in Model

Tags:

python

django

There are similar questions but none recent and based on Django 3 so here it goes:

I am using py nanoid to generate some unique IDs so in my models I have

from nanoid import generate

and then

class Work(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    published = models.BooleanField(False)
    date = models.DateTimeField()
    nanoid = models.CharField(max_length=15, default = generate(size=10) )
    
    
    def __str__ (self):
        return self.title

my aim is to ensure that a new nanoid is generated each time a new work post is added. At the moment is the same repeated each time I try to add a new Work via admin.

I read some replies about creating a custom class but I am a bit at a loss here!

like image 954
devnull Avatar asked Nov 01 '25 22:11

devnull


2 Answers

If you pass a function as a default it must be one that takes no arguments. You can use functools.partial to turn generate into a function that takes no args and has size=10 set as the default

from functools import partial

class Work(models.Model):
   ...
   nanoid = models.CharField(max_length=15, default=partial(generate, size=10))
like image 79
Iain Shelvington Avatar answered Nov 03 '25 12:11

Iain Shelvington


You can override the save method on your model to do it, also you have to create a helper function to check if the nanoid on your model already exists in your persistent storage.

class Work(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    published = models.BooleanField(False)
    date = models.DateTimeField()
    nanoid = models.CharField(max_length=15)
    
    def save(self, *args, **kwargs):
        nanoid = generate_id()
        super(Work, self).save(*args, **kwargs)

    def __str__ (self):
        return self.title

# Helpers
def generate_id():
    """
    Generate nanoid unique code.
    """
    n_id = generate(size=10)
    while not is_available_code(n_id):
        n_id = generate(size=10)
    return n_id

def is_available_id(id):
    """
    Validate Id.
    """
    return not id_is_nanoid(id)

def id_is_nanoid(id):
    return Work.objects.filter(nanoid=id).exists()
like image 27
Carlos Saldana Avatar answered Nov 03 '25 11:11

Carlos Saldana