[Django]-CharField with fixed length, how?

50👍

CharField database model field instances only have a max_length parameter, as indicated in the docs. This is probably because there is only a max character length contraint equivalent in SQL.

Form Field CharField objects, on the other hand, do have a min_length parameter. So you’d have to write a custom ModelForm for this specific model and override the default admin model form with the custom one.

Something like that:

# admin.py

from django import forms

...

class VolumeForm(forms.ModelForm):
    volumenumber = forms.CharField(max_length=4, min_length=4)

    class Meta:
        model = Volume


class VolumeAdmin(admin.ModelAdmin):
    form = VolumeForm

...

admin.site.register(Volume, VolumeAdmin)
👤Haes

122👍

Kind of along the same lines as above, but for what it’s worth you could also go ahead with MinLengthValidator which django supplies. Worked for me. The code would look something like this:

from django.core.validators import MinLengthValidator
...
class Volume(models.Model):
volumenumber = models.CharField('Volume Number', max_length=4, validators=[MinLengthValidator(4)])
...
👤Chetan

102👍

You don’t even have to write a custom one. Just use the RegexValidator which Django supplies.

from django.core.validators import RegexValidator

class MyModel(models.Model):
    myfield = models.CharField(validators=[RegexValidator(regex='^.{4}$', message='Length has to be 4', code='nomatch')])

From the Django Docs: class RegexValidator(\[regex=None, message=None, code=None\])

regex: A valid regular expression to match. For more on regex in Python check this excellent HowTo:
http://docs.python.org/howto/regex.html

message: The message returned to the user in case of failure.

code: error code returned by ValidationError. Not important for your usage case, you can leave it out.

Watch out, the regex suggested by me will allow any characters including whitespace. To allow only alphanumeric characters, substitute the ‘.’ with ‘\w’ in the regex argument. For other requirements, ReadTheDocs ;).

👤tBuLi

17👍

You can write a custom Validator as suggested by @Ben. As of the date of this answer the instructions for doing this can be found at https://docs.djangoproject.com/en/dev/ref/validators/

The code would be something like this (copying from the link):

from django.core.exceptions import ValidationError

def validate_length(value,length=6):
    if len(str(value))!=length:
        raise ValidationError(u'%s is not the correct length' % value)

from django.db import models

class MyModel(models.Model):
    constraint_length_charField = models.CharField(validators=[validate_length])
👤tjb

0👍

Yet another implementation using custom model field:

from django.core.validators import BaseValidator
from django.db import models
from django.utils.deconstruct import deconstructible


@deconstructible
class FixedLengthValidator(BaseValidator):
    message = 'Ensure this value has %(limit_value)d character (it has %(show_value)d).'
    code = 'length'

    def compare(self, a, b):
        return a != b

    def clean(self, x):
        return len(x)


class FixedLengthCharField(models.CharField):
    def __init__(self, *args, length, **kwargs):
        self.length = length
        kwargs['max_length'] = length
        super().__init__(*args, **kwargs)
        self.validators.insert(0, FixedLengthValidator(length))

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        del kwargs['max_length']
        kwargs['length'] = self.length
        return name, path, args, kwargs

Leave a comment