【问题标题】:Convert all CharField Form Field inputs to lowercase in Django forms将所有 CharField 表单字段输入转换为 Django 表单中的小写
【发布时间】:2014-06-19 17:51:18
【问题描述】:

我正在使用 Django 表单进行用户注册,用户可以在其中输入优惠券代码。我希望在优惠券代码字段中输入的所有字符都转换为小写。我尝试在保存方法、自定义清理方法和自定义验证器中使用 .lower() ,但这些方法没有运气。下面是我的代码。

class StripeSubscriptionSignupForm(forms.Form):
    coupon = forms.CharField(max_length=30,
        required=False,
        validators=[validate_coupon],
        label=mark_safe("<p class='signup_label'>Promo Code</p>")

    def save(self, user):
        try:
            customer, created = Customer.get_or_create(user)
            customer.update_card(self.cleaned_data["stripe_token"])
            customer.subscribe(self.cleaned_data["plan"], self.cleaned_data["coupon"].lower())
        except stripe.StripeError as e:
            # handle error here
            raise e

如上所述,我也尝试了一种清洁方法,但这也不起作用:

def clean_coupon(self):
    return self.cleaned_data['coupon'].lower()

【问题讨论】:

  • 实际上,forms.Form 没有任何名为save 的方法。所以请改用ModelForm 或在视图中保存优惠券。
  • @ruddra: 你确定 forms.form 没有save 方法吗?
  • 我是。您可以在 Django 源代码中检查自己。
  • @ruddra... 有趣,但保存方法的其余部分在我的 StripeSubscriptionSignupForm 类中工作(除了 .lower() 代码)。
  • 我检查了,保存应该可以工作,因为你创建了这个方法,而不是覆盖任何东西。

标签: python django python-2.7


【解决方案1】:

尝试在表单中使用带有小部件的 css 文本转换,如下所示:

class StripeSubscriptionSignupForm(forms.Form):
    coupon = forms.CharField(max_length=30,
        required=False,
        validators=[validate_coupon],
        label=mark_safe("<p class='signup_label'>Promo Code</p>")
        widget=TextInput(attrs={'style': 'text-transform:lowercase;'})
        )

【讨论】:

  • 这是一个聪明的方法。但是,我希望这些字段能够显示大写字符,这些字符在提交表单后会转换为小写。另外,我认为小部件代码需要是: widget=forms.TextInput(attrs={'style': 'text-transform:lowercase;'}
  • 鼓励某种风格并防止因错误发生而感到沮丧的酷方法
【解决方案2】:

我自己在确保用户模型中的电子邮件字段仅保存为小写时遇到了这个问题。我在下面概述的方法的优点是您可以控制表单中每个字段的格式 - 与上面选择的答案相反,无论您是否愿意,都会将所有字段转换为小写。

对我来说,我相信上面的 OP 的问题是清理后的值现在确实是小写的,但是 HTML 页面(在验证和清理后呈现的页面)显示了预清理的值(即仍在大写),这会使用户感到困惑。发生的事情是表单字段值仍然按照初始数据,即 X@Y.com 并且清理后的数据实际上是 x@y.com 。

处理提交的表单后:

>>>user_form.cleaned_data['email']
'x@y.com'

>>>user_form['email'].value()
'X@Y.com'

模板使用 user_form['email'].value() 而不是 user_form.cleaned_data['email'] 提供的值,因此用户认为他的电子邮件已以大写形式保存,而实际上它已被保存以小写形式保存。

在这种情况下,将 user_form 显示在模板中的已清理字段返回给客户端的最简单方法是在保存后直接重新加载已保存的表单。按照以下两个例子(一个保存到数据库,一个不保存到数据库)。

forms.py

from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
    """
    UserForm is a simple form to allow a user to change his/her name and email.
    """
    class Meta:
        model = User 
        fields = ['first_name', 'last_name', 'email']

    def clean_email(self):
        """
        ensure that email is always lower case.
        """
        return self.cleaned_data['email'].lower()

在views.py中

def post(self, request):
    user_form = UserForm(request.POST, instance=request.user)
    if user_form.is_valid():
        user_form.save()  # using the provided save from Modelform in this case
        user_form = UserForm(instance=request.user)  # reload the amended user data
    return render(request, 'myApp/user_details.html',{'user_form': user_form})

这里的关键行在views.py中,user_form = UserForm(instance=request.user),表单被重新加载的地方。这里的效果是在呈现给用户之前用清理过的(在这种情况下保存)数据重新填充表单。 现在,您可以通过为这些字段调用适当的 clean_fieldname 将表单中的每个字符字段更改为小写。

注意:如果您不与数据库交互(或者只是不想从数据库中重新加载),您可以按如下方式重新填充表单:

def post(self, request):
    user_form = UserForm(request.POST) #gather the post'ed data
    if user_form.is_valid():
        user_form.process()  # process the gathered cleaned data            
        user_form = UserForm(
            {'email': user_form.cleaned_data['email'],
            'first_name': user_form.cleaned_data['first_name'],
            'last_name': user_form.cleaned_data['last_name'],}
        ) # reload the form       
    return render(request, 'myApp/user_details.html',{'user_form': user_form})

作为这里的一个小优化,你可以使用内置的检查:

 if user_form.has_changed():

从 is_valid() 检查开始(或与它一起检查) - 如果表单上没有任何更改,通常不需要保存或处理表单。

【讨论】:

    【解决方案3】:

    解决方案是创建一个自定义表单字段,它允许您覆盖 to_python 方法,然后可以在其中修改表单字段的原始值。

    class CouponField(forms.CharField):
        def to_python(self, value):
            return value.lower()
    
    
    class StripeSubscriptionSignupForm(forms.Form):
        coupon = CouponField(max_length=30,
            required=False,
            validators=[validate_coupon],
            label=mark_safe("<p class='signup_label'>Promo Code</p>")
        )
    

    【讨论】:

    • 不应该to_python覆盖做return self.super().to_python(value).lower()而不是return value.lower()吗?我们不是这样跳过验证吗?
    • 还有,forms.CharField 好像不存在,不应该是models.CharField吗?
    • @SebastiánVansteenkiste 看这里:docs.djangoproject.com/en/2.2/ref/forms/widgets/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多