为什么在Django中更新对象模型不像预期的那样工作?

ui7jx7zq  于 2023-10-21  发布在  Go
关注(0)|答案(2)|浏览(118)

这似乎很奇怪
我在Django中有以下模型:

class CustomUser(AbstractUser):
    first_name = models.CharField(_("first name"), max_length=20)
    last_name = models.CharField(_("last name"), max_length=20)
    email = models.EmailField(_('email address'), blank=False, unique=True)
    validated_account = models.BooleanField(_('validated account'), blank=False, default=False)
    phone = PhoneNumberField(null=False, blank=False, unique=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

我有下面的表单来编辑模型:

class CustomUserChangeForm(UserChangeForm):
    password = None
    
    class Meta(UserChangeForm.Meta):
        model = CustomUser
        fields = ["first_name", "last_name", "email", "phone", "username"]

这是我编辑模型的视图:

@user_passes_test(lambda u: u.is_authenticated, "users:login")
def edit_profile(request):
    if request.method == "POST":
        print(request.POST)
        form = CustomUserChangeForm(request.POST, instance=request.user)
        print(form)

        if form.is_valid():
            user = form.save()
            auth_login(request, user)

            messages.success(request, "Edition successful.")

            return redirect("dashboard:cases")

        messages.error(
            request, "Unsuccessful Edition. Invalid information.")
    else:
        form = CustomUserChangeForm(instance=request.user)
        

    return render(request=request, template_name="dashboard/edit_profile.html", context={"edit_profile_form": form})

这是视图调用的打印结果:

<QueryDict: {'csrfmiddlewaretoken': ['DbmuCTIOAXdP96Ozrcsf3YXSCxQ1lusywgLz4OLh5FAHrjas25inxqIt0kS9syaj'], 'first_name': ['Super'], 'last_name': ['User'], 'email': ['[email protected]'], 'phone': ['+0043328107a'], 'username': ['admin']}>
<tr>
    <th><label for="id_first_name">First name:</label></th>
    <td>
      <input type="text" name="first_name" value="Super" maxlength="20" required id="id_first_name">
    </td>
  </tr>
  <tr>
    <th><label for="id_last_name">Last name:</label></th>
    <td>
      <input type="text" name="last_name" value="User" maxlength="20" required id="id_last_name">
    </td>
  </tr>
  <tr>
    <th><label for="id_email">Email address:</label></th>
    <td>
      <input type="email" name="email" value="[email protected]" maxlength="254" required id="id_email">
    </td>
  </tr>
  <tr>
    <th><label for="id_phone">Phone:</label></th>
    <td>
      <input type="tel" name="phone" value="+0043328107" maxlength="128" required id="id_phone">
    </td>
  </tr>
  <tr>
    <th><label for="id_username">Username:</label></th>
    <td>
      <input type="text" name="username" value="admin" maxlength="150" autocapitalize="none" autocomplete="username" required id="id_username">
        <br>
        <span class="helptext">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</span>
    </td>
  </tr>

为什么生成的表单不包含电话号码中的最后一个字母?在POST请求中,一个末尾有字母的电话号码清晰地出现。我希望它是无效的,而形式是有效的。
我做错了什么?谢谢你的帮助

wgmfuz8q

wgmfuz8q1#

我假设PhoneNumberField来自django-phonenumber-field。如果是的话

简答:是图书馆在做。
长回答:

tel类型的html输入的指定行为是允许几乎所有字符,因为电话号码有不同的语法。
与URL和电子邮件类型不同,电话类型不强制执行特定语法。这是故意的;实际上,由于存在各种各样的有效电话号码,电话号码字段往往是自由格式的字段。
除了回车/r或换行符/n之外,输入将允许您输入任何内容,包括字母和数字的混合。这就是为什么POST数据包含“无效”字符的原因。
但是你在这个字段中使用了PhoneNumberField,这就是造成“意外”行为的原因。Django表单实现了to_python方法,负责将用户的html输入转换为Python对象。返回的值是表单/模型的clean方法中使用的值。这就是“意外”行为的起源。
PhoneNumberField覆盖这个to_python方法,当提供一个字符串时(HTML表单总是这样),它使用phonenumbersparse函数解析输入。这就是删除绑定表单字段值中的无效字符的原因。
下面是一个演示x1c 0d1x
您可以看到national_number属性已经删除了尾随的无效字符。它也会解析电话号码之间的无效字符。parse函数的doc字符串中解释了它是如何实现的:
“该方法相当宽松,它在输入文本(原始输入)中查找一个数字,而不检查字符串是否肯定只是一个电话号码。要做到这一点,它会忽略标点符号和空格,以及数字之前的任何文本(例如,a领导电话:“)并修剪非数字位。它将接受任何格式的数字(E164,国家,国际等),假设它可以用提供的defaultRegion解释。如果它认为这是一个类型为“1800 MICROSOFT”的虚数,它也会尝试将任何字母字符转换为数字。
同样,这假设你使用的是django-phonenumber-field,如果不是,那么,我就完蛋了。

krcsximq

krcsximq2#

你确定表格有效吗?根据你在那里的视图代码,如果它无效,它将再次显示表单。如果它是有效的,它会重新引导你。

相关问题