Krisnadi
Krisnadi

Reputation: 681

Django model - set default charfield in lowercase

How to set default charfield in lowercase? This is my model:

class User(models.Model):
    username = models.CharField(max_length=100, unique=True)
    password = models.CharField(max_length=64)
    name = models.CharField(max_length=200)
    phone = models.CharField(max_length=20)
    email = models.CharField(max_length=200)

    def __init__(self, *args, **kwargs):
        self.username = self.username.lower()

I tried the __init__ but it doesn't work. I want to make the username in lowercase every time new record saved. Thanks.

Upvotes: 35

Views: 25991

Answers (5)

Danil
Danil

Reputation: 3568

While overwriting save() method is a valid solution. I found it useful to deal with this on a Field level as opposed to the Model level by overwriting get_prep_value() method.

This way if you ever want to reuse this field in a different model, you can adopt the same consistent strategy. Also the logic is separated from the save method, which you may also want to overwrite for different purposes.

For this case you would do this:

class NameField(models.CharField):
    # Ensure valid values will always be using just lowercase
    def get_prep_value(self, value):
        value = super().get_prep_value(value)
        return value if value is None else value.lower()

class User(models.Model):
    username = models.CharField(max_length=100, unique=True)
    password = models.CharField(max_length=64)
    name = NameField(max_length=200)
    phone = models.CharField(max_length=20)
    email = models.CharField(max_length=200)

Upvotes: 78

Arnold Ighiwiyisi
Arnold Ighiwiyisi

Reputation: 150

In my case I had a recipient_name field that I needed to make all lower case when it is stored on DB

class LowerField(models.CharField):

    def get_prep_value(self, value):
        return str(value).lower()

class Recipients(models.Model):
    
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='recipients', on_delete=models.CASCADE, )
    recipient_account_number = models.IntegerField()
    recipient_name = LowerField(max_length=30)
    recipient_bank_name = models.CharField(max_length=30)
    date = models.DateTimeField(auto_now=True, verbose_name='Transaction Date')
    
    class Meta:
        ordering = ['-date']

    def __str__(self):
        return self.recipient_name

    def get_absolute_url(self):
        return reverse('recipient-detail', kwargs={'pk': self.pk})

Similarly, you can apply to another table called Transactions in your app, like this

class Transactions(models.Model):

    transaction_type = (
        ('transfer', 'Transfer'),
        )

    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='transactions', on_delete=models.CASCADE, )
    bank_name = LowerField(max_length=50)

Upvotes: 1

sralvins
sralvins

Reputation: 327

signals also works

from django.db.models.signals import pre_save

@receiver(pre_save, sender=YourModel)
def to_lower(sender, instance=None, **kwargs):
    instance.text = instance.text.lower() if  \
        isinstance(instance.text, str) else ''

Upvotes: 0

Pyro Fury
Pyro Fury

Reputation: 5

def save(self, force_insert=False, force_update=False):
        self.YourFildName = self.YourFildName.upper()
        super(YourFomrName, self).save(force_insert, force_update)

Upvotes: -2

Avinash Raj
Avinash Raj

Reputation: 174706

Just do it in the save method. ie, override the save method of Model class.

def save(self, *args, **kwargs):
    self.username = self.username.lower()
    return super(User, self).save(*args, **kwargs)

Upvotes: 34

Related Questions