Home > Enterprise >  Get DataError: value too long for type character varying for every string
Get DataError: value too long for type character varying for every string

Time:04-28

I use Django Postgres for my project. I tried to implement user registration, but when I try to send a form with username and password, I get database error psycopg2.errors.StringDataRightTruncation: value too long for type character varying(32)

That error appears with every string as a password, even its length less than 32. I tried to print form values, so they are the same that I typed. What can be the reason for value too long error?

models.py

class Person(AbstractUser):
    username = models.fields.CharField(max_length=50,unique=True)
    password = models.fields.CharField(max_length=32)

forms.py

class RegisterForm(ModelForm):
    username = forms.CharField(max_length=100)
    password = forms.CharField(widget=PasswordInput())

    class Meta:
        model = Person
        fields = ["username", "password"]

views.py

def register(request):
    context={}
    if request.method == 'POST':
        form = RegisterForm(data=request.POST)
        if form.is_valid():
            username = request.POST['username']
            password = request.POST['password']
            print('username: ' username)
            print('password: ' password)
            if len(Person.objects.filter(username=username))==0:
                Person.objects.create_user(username=username, password=password)
            else:
                context['form_errors']=['Person with this username already exists']
    else:
        form = RegisterForm()

error enter image description here

CodePudding user response:

Django will, by default, hash the password as security measure, and thus the hashed password is longer than 32 characters. Indeed, in the How Django stores passwords section of the documentation, it shows that it stores the password as:

<algorithm>$<iterations>$<salt>$<hash>

an example could for example be:

pbkdf2_sha256$15000$Pjun1TMGEQnM$lShdzU33covbDNiqGVDffdHh/86VaECJlaaNXchT0ew=

It is impossible to reconstruct the original password (given the hasher is a safe hasher), only to check if the passwords match. If someone manages to get access to the database, that person still can not read the real passwords. Since people often tend to use the same password on multiple sites, that would be a severe security risk.

You thus need more space to store the hashed passwords. Django's standard user model uses 128 characters. So you implement this as:

class Person(AbstractUser):
    username = models.fields.CharField(max_length=50, unique=True)
    password = models.fields.CharField(max_length=128)

You can let the form check if the username is unique and thus work with:

class RegisterForm(ModelForm):

    class Meta:
        model = Person
        fields = ['username', 'password']
        widgets = {
            'password': PasswordInput()
        }

    def save(self, *args, commit=True, **kwargs):
        person = super().save(*args, commit=commit, **kwargs)
        person.set_password(self.cleaned_data['password'])
        if commit:
            person.save()
        return person

By not specifying the form fields manually, Django will also validate the maximum length for the username (50 characters), and check its uniqness.

You then can use as view:

def register(request):
    if request.method == 'POST':
        form = RegisterForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('name-of-some-view')
    else:
        form = RegisterForm()
    context = {'form': form}
    # …
  • Related