Home > Mobile >  Django.models custom blank value
Django.models custom blank value

Time:12-05

thanks for tanking the time to look at this query.

I'm setting an ID field within one of my Django models. This is a CharField and looks like the following:

my_id = models.CharField(primary_key=True, max_length=5,
                           validators=[RegexValidator(
                               regex=ID_REGEX,
                               message=ID_ERR_MSG,
                               code=ID_ERR_CODE
                           )])

I would like to add a default/blank or null option that calls a global or class function that will cycle through the existing IDs, find the first one that doesn't exist and assign it as the next user ID. However, when I add the call blank=foo() I get an error code that the function doesn't exist.

Best, pb

Edit1: I also tried using a separate utils file and importing the function, but (unsurprisingly) I get a circular import error as I need the call the class to get the objects.

Edit2 (Reply to Eugene): Tried that, solved the circular import but I'm getting the following error:

    TypeError: super(type, obj): obj must be an instance or subtype of type

Previously my override of the save function worked perfectly:

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Staff, self).save(*args, **kwargs)

The custom id function:

def get_id_default():

    from .models import MyObj
    for temp_id in range(10_000, 100_000):
        try:
            MyObj.objects.get(my_id=str(temp_id))
        except ObjectDoesNotExist:
            break  # Id doesn't exist

    return str(hive_id)

Edit 3 (Reply to PersonPr7): Unfortunately, the kwargs doesn't seem to have my id in it. Actually, after having a print the kwargs dictionary comes back empty.

Save function:

    def save(self, *args, **kwargs):

        print(kwargs) #  --> Returns {}
        if kwargs["my_id"] is None:
            kwargs["my_id"] = self.get_id_default()

        self.full_clean()
        super(Staff, self).save(*args, **kwargs)

Where the get_id_default is a class function:

    def get_id_default(self):
        for temp_id in range(10_000, 100000):
            try:
                self.objects.get(my_id=str(temp_id))
            except ObjectDoesNotExist:
                break  # Id doesn't exist

        return str(temp_id)

Solution1:

For those who are may be struggling with this in the future:

Create a utils/script .py file (or whatever you wanna call it) and create your custom script inside.

from .models import MyModel

def my_custom_default:
    # your custom code
    return your_value

Inside the main.models.py file. 

from django.db import models
from .my_utils import my_custom_default

class MyModel(model.Model):
    my_field = models.SomeField(..., default=my_custom_default)

Solution2: Create a static function within your Model class that will create your default value.

@staticmethod
def get_my_default():
    # your logic
    return your_value
    # NOTE: Initially I had the function use self
    # to retrieve the objects (self.objects.get(...)) 
    # However, this raised an exception: AttributeError: 
    # Manager isn't accessible via Sites instances

When setting up your model give your field some kind of default i.e. default=None

Additionally, you need to override the models save function like so:

def save(self, *args, **kwargs):
    if self.your_field is None:
        self.my_field = self.get_my_default()
    
    self.full_clean()
    super().save(*args, **kwargs)

CodePudding user response:

Try overriding the Model's save method and performing the logic there:

def save(self, *args, **kwargs):
    #Custom logic
    super().save(*args, **kwargs)

Edit: You don't need to use **kwargs. You can access your whole model from the save method and loop over objects / ids.

  • Related