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

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

我的项目使用 Django+Postgres。我尝试实现用户注册,但是当我尝试发送包含用户名和密码的表单时,出现数据库错误 psycopg2.errors.StringDataRightTruncation: value too long for type character varying(32)

该错误出现在每个字符串作为密码时,即使其长度小于 32。我尝试打印表单值,所以它们与我输入的相同。值太长错误的原因是什么?

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()

错误

Django 默认情况下,散列 密码作为安全措施,因此散列密码长于 32 个字符。事实上,在 How Django stores passwords section of the documentation 中,它表明它将密码存储为:

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

一个例子可以是:

pbkdf2_sha256000$Pjun1TMGEQnM$lShdzU33covbDNiqGVDffdHh/86VaECJlaaNXchT0ew=

不可能重建原始密码(假定散列器是 safe 散列器),只能检查密码是否匹配。如果有人设法访问数据库,该人仍然无法读取真实密码。由于人们通常倾向于在多个站点上使用相同的密码,这将是一个严重 安全风险。

因此您需要更多 space 来存储 散列 密码。 Django 的标准用户模型使用 128 个字符。所以你将其实现为:

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

您可以让表单检查 username 是否是唯一的,因此可以使用:

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.<strong>set_password(</strong>self.cleaned_data['password']<strong>)</strong>
        if commit:
            person.save()
        return person

通过不手动指定表单字段,Django 还将验证用户名的最大长度(50 个字符),并检查其唯一性。

然后您可以用作视图:

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